I want to set a DataTrigger for multiple DataTemplate but I am not sure if there is way to do that? I have view structured like below
<ItemsControl ItemsSource="{Binding Collection}"
AlternationCount="2"
ItemTemplateSelector="{StaticResource RowSelector}" >
<local:HeaderTemplateSelector x:Key="RowSelector"
NormalTemplate="{StaticResource NormalTemplate}"
ExpanderTemplate1="{StaticResource ExpanderTemplate1}"
ExpanderTemplate2="{StaticResource ExpanderTemplate2}"
ExpanderTemplate3="{StaticResource ExpanderTemplate3}" />
<DataTemplate x:Key="NormalTemplate" ...>
<stackpanel x:Name="main"
<DataTemplate x:Key="ExpanderTemplate1" ...>
<Grid x:Name="main" ..>
<DataTemplate x:Key="ExpanderTemplate2" ...>
<Expander x:Name="main"
<DataTemplate x:Key="ExpanderTemplate3" ...>
<Textblock x:Name="main" ...>
I want this data trigger which provides alternative background for rows, the trigger defined below
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Blue" TargetName="main"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="black" TargetName="main"/>
</Trigger>
</DataTemplate.Triggers>
I can add this to the end of each DataTemplate and it works fine but it mean that I have to duplicate the some code 4 times, is there any way to avoid that? (I know I can use datagrid but it is overkill for this simple structure)
You can try to set the trigger with the style:
<Style TargetType="Panel" x:Key="AlternatelyPainted">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="1">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
(code thankfully stolen from this answer) and use it in your templates:
<DataTemplate x:Key="NormalTemplate" ...>
<StackPanel Style="{StaticResource AlternatelyPainted}">
...
</StackPanel>
</DataTemplate>
etc.
Edit: if you want the style to be universal, not Panel
-specific, you can try the following trick:
<Style x:Key="AlternatelyPainted">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="0">
<Setter Property="Panel.Background" Value="Red"/>
<Setter Property="Control.Background" Value="Red"/>
<Setter Property="TextBlock.Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="1">
<Setter Property="Panel.Background" Value="Blue"/>
<Setter Property="Control.Background" Value="Blue"/>
<Setter Property="TextBlock.Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
(removed the TargetType
and added explicit types to the property names). Note that TextBlock
doesn't inherit its Background
, so we need an additional line for it.