Here is an example of how you may change the style of an element based on the data trigger:
<StackPanel>
<Control Focusable="False">
<Control.Template>
<ControlTemplate>
<!--resources-->
<ControlTemplate.Resources>
<Style TargetType="Button" x:Key="primary">
<Setter Property="Content" Value="Primary style"/>
</Style>
<Style TargetType="Button" x:Key="secondary">
<Setter Property="Content" Value="Secondary style"/>
</Style>
</ControlTemplate.Resources>
<!--content-->
<Button Style="{StaticResource primary}" x:Name="button"/>
<!--triggers-->
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}" Value="true">
<Setter TargetName="button" Property="Style" Value="{StaticResource secondary}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin,RelativeSource={RelativeSource Self}}" Value="true">
<Setter TargetName="button" Property="Style" Value="{StaticResource secondary}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Control.Template>
</Control>
<Button Content="A normal button"/>
</StackPanel>
In this example, Control
is a wrapper element which will host the desired element in its control template. It is required to be in the control template if you wish to access it by name. A set of data triggers are defined in the control template's trigger, which will apply the style on the desired element (button) as needed.
I did not find a way to avoid duplicate setters. Perhaps the ability to swap/apply the style may help you achieve the same result.
If you do not wish to go for the control template approach, you may make use of attached properties or an unused Tag
property in the element. In this example, we will take advantage of two way binding to achieve the same result.
Example:
<StackPanel>
<Grid>
<!--content-->
<Button Style="{Binding Tag,RelativeSource={RelativeSource FindAncestor,AncestorType=Grid}}"/>
<Grid.Style>
<Style TargetType="Grid">
<!--resources-->
<Style.Resources>
<Style TargetType="Button" x:Key="primary">
<Setter Property="Content" Value="Primary style"/>
</Style>
<Style TargetType="Button" x:Key="secondary">
<Setter Property="Content" Value="Secondary style"/>
</Style>
</Style.Resources>
<Setter Property="Tag" Value="{StaticResource primary}"/>
<!--triggers-->
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}" Value="true">
<Setter Property="Tag" Value="{StaticResource secondary}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin,RelativeSource={RelativeSource Self}}" Value="true">
<Setter Property="Tag" Value="{StaticResource secondary}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
<Button Content="A normal button"/>
</StackPanel>
Try it and see if this helps you to achieve the desired result.