I am trying to bind visibility of a styled control to the condition that its tag is equal to the selected index of a TabControl.
I use RelativeSource TemplatedParent
but it's not being set, and I suspect it's because I am not setting Template
property in Style.
Here is my code:
<Grid x:Name="Telas" Grid.Column="1">
<Grid.Resources>
<vw:TagIsIndexBooleanConverter x:Key="TagIsIndexBooleanConverter"/>
<Style x:Key="SelectedIndexVisibleStyle" TargetType="UserControl">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource TagIsIndexBooleanConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource TemplatedParent}"/>
<Binding Path="SelectedIndex" ElementName="menu"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<vw:TelaColetaView
x:Name="telaColeta"
DataContext="{Binding TelaColetaVM}"
Style="{StaticResource SelectedIndexVisibleStyle}"
Tag="0"/>
<vw:TelaPacientesView
x:Name="telaPacientes"
DataContext="{Binding TelaPacientesVM}"
Style="{StaticResource SelectedIndexVisibleStyle}"
Tag="1"/>
<vw:TelaConfiguraçõesView
x:Name="telaConfigurações"
DataContext="{Binding TelaConfiguraçõesVM}"
Style="{StaticResource SelectedIndexVisibleStyle}"
Tag="4"/>
</Grid>
And converter:
public class TagIsIndexBooleanConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Any(v => v == null || v == DependencyProperty.UnsetValue))
return Binding.DoNothing;
var tag = System.Convert.ToInt32(values[0]);
var index = System.Convert.ToInt32(values[1]);
var result = tag == index;
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can't use TemplatedParent
in this case because there isn't one; that's meant to used inside a ControlTemplate
to specify that the source for the binding is the control that you're applying the template to.
<Binding Path="Tag" RelativeSource="{RelativeSource TemplatedParent}"/>
But this isn't inside a ControlTemplate
. Instead, Tag
is just a property of the thing you're styling. Ordinarily you'd do a trigger like this for Tag
:
<Trigger Property="Tag" Value="0">
...but you need a multibinding to get the SelectedIndex
from menu
, and it's got to be a MultiDataBinding
because you need to specify ElementName
.
So you need a binding. To bind to one of your own properties instead of a property of your DataContext
, you bind with a RelativeSource
of Self
:
<Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
OP also found he had to set the TargetType
of the Style
to "UserControl"
, for the Tag
binding to work.