Reputation: 198
I'm building a menu with WPF but I want to simplify the code creating a new style. At the moment, the menu is working great:
<Button Name="btnMenu1" Grid.Row="0" Content="Button One" Click="BtnMenu1_Click">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding [0].Selected}" Value="True">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding [0].Selected}" Value="False">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Name="btnMenu2" Grid.Row="1" Content="Button Two" Click="BtnMenu2_Click">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding [1].Selected}" Value="True">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding [1].Selected}" Value="False">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Imagine that I need to add 10 or 15 buttons to the menu, can you imagine the amount of code? My idea is to simplify the code:
<Button Name="btnMenu1" Grid.Row="0" Style="{StaticResource StyleButtonMenu}" Content="Button One" Click="BtnMenu1_Click"/>
<Button Name="btnMenu2" Grid.Row="1" Style="{StaticResource StyleButtonMenu}" Content="Button Two" Click="BtnMenu2_Click"/>
<Button Name="btnMenu3" Grid.Row="2" Style="{StaticResource StyleButtonMenu}" Content="Button Three" Click="BtnMenu3_Click"/>
<Button Name="btnMenu4" Grid.Row="3" Style="{StaticResource StyleButtonMenu}" Content="Button Four" Click="BtnMenu4_Click"/>
<Button Name="btnMenu5" Grid.Row="4" Style="{StaticResource StyleButtonMenu}" Content="Button Five" Click="BtnMenu5_Click"/>
And the code style could be something like this:
<Style x:Key="StyleButtonMenu" TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Style.Triggers>
<DataTrigger Binding="{Binding Selected}" Value="True">
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger>
<DataTrigger Binding="{Binding Selected}" Value="False">
<Setter Property="Foreground" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
My problem here is: How can I work with Binding
s in DataTrigger
to treat the property Selected
?
I have a List
with properties and when some property change, I need to update UI.
As I said at the top, the code works great, I just want to create a generic style and treat bindings in DataTrigger
.
Upvotes: 0
Views: 1099
Reputation: 22079
For your pretty static example, your could bind the Tag
in your style using a DataTrigger
.
<Style x:Key="StyleButtonMenu" TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Tag.Selected, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
Then, you could bind the concrete data context to the Tag
of each button.
<Button Name="btnMenu1" Grid.Row="0" Tag="{Binding [0]}" Style="{StaticResource StyleButtonMenu}" Content="Button One" Click="BtnMenu1_Click"/>
<Button Name="btnMenu2" Grid.Row="1" Tag="{Binding [1]}" Style="{StaticResource StyleButtonMenu}" Content="Button Two" Click="BtnMenu2_Click"/>
<Button Name="btnMenu3" Grid.Row="2" Tag="{Binding [2]}" Style="{StaticResource StyleButtonMenu}" Content="Button Three" Click="BtnMenu3_Click"/>
<Button Name="btnMenu4" Grid.Row="3" Tag="{Binding [3]}" Style="{StaticResource StyleButtonMenu}" Content="Button Four" Click="BtnMenu4_Click"/>
<Button Name="btnMenu5" Grid.Row="4" Tag="{Binding [4]}" Style="{StaticResource StyleButtonMenu}" Content="Button Five" Click="BtnMenu5_Click"/>
However, there is a better way. Whenever you try to display a collection of data items, consider using an ItemsControl
or any derived type that is appropriate for your use-case. Here, you could use an ItemsControl
with a data template, since you do not need selection or anything special.
<Style x:Key="MenuButtonStyle" TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Selected}" Value="True">
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="MenuItemTemplate">
<Button Style="{StaticResource MenuButtonStyle}"
Content="{Binding Name}"
Command="{Binding DoSomething}"
CommandParameter="{Binding}">
</Button>
</DataTemplate>
This data template assumes that your menu item data types contain a Name
, DoSomething
and the Selected
property from your question. Depending on your requirements, the DoSomething
command might also be definded on the parent data context. This command would handle the button click.
Instead of a Grid
with hard-coded buttons, you can now bind the items collection (here MenuItems
) to an ItemsControl
with the aforementioned data template for your items.
<ItemsControl ItemsSource="{Binding MenuItems}"
ItemTemplate="{StaticResource MenuItemTemplate}"/>
Upvotes: 1