I have the following Button and Style in WPF and I need to generalize the Binding in the DataTrigger section because I have near 10 similar buttons in the same Window and each button should be binded to a different property (SelectedPositions, SelectedAgencies, ....). Is it possible to implement?
<Button x:Name="btnPosition"
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding PositionFilterCommand}"
Content="{l:Translate position}"
Style="{StaticResource NewButtonStyle}" />
<Style x:Key="NewButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Height" Value="22" />
<Setter Property="Width" Value="Auto" />
<Setter Property="FontFamily" Value="OpenSans" />
<Setter Property="FontSize" Value="13" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Margin" Value="10,2,10,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="3">
<Grid x:Name="gridButton" Background="#54728e">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image x:Name="img"
Grid.Column="0"
Width="24"
Height="24"
Source="Img/tick-white.png"
Visibility="Visible" />
<Rectangle x:Name="rect"
Grid.Column="1"
Fill="#54728e"
RadiusX="3"
RadiusY="3" />
<ContentPresenter Grid.Column="1"
Margin="5,0,5,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding SelectedPositions}" Value="{x:Static sys:String.Empty}">
<Setter TargetName="rect" Property="Fill" Value="#8bbcdf" />
<Setter TargetName="img" Property="Visibility" Value="Collapsed" />
<Setter TargetName="gridButton" Property="Background" Value="#8bbcdf" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A DataTrigger allows you to set property values when the property value of the data object matches a specified Value. For example, if you are displaying a list of Employee objects, you may want the foreground color to be different based on each Employee's current attendance.
Basically, a trigger enables you to change property values or take actions based on the value of a property. So, it basically allows you to dynamically change the appearance and/or behavior of your control without having to create a new one.
could you provide me an example of what you explained?
Sure,
1 - Using Tag
In your Style
have your DataTrigger
as:
<DataTrigger Binding="{Binding Path=Tag,
RelativeSource={RelativeSource Self}}"
Value="{x:Static sys:String.Empty}">
...
</DataTrigger>
as for usage:
<Button x:Name="btnPosition"
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding PositionFilterCommand}"
Content="{l:Translate position}"
Tag="{Binding SelectedPositions}"
Style="{StaticResource NewButtonStyle}" />
2 - Using Attached Property:
"local:" refers to the xaml namespace alias of your application or if you use different namespaces, the namespace where MyCustomPropertyCollection
is declared.
code-behind:
public class MyCustomPropertyCollection {
public static readonly DependencyProperty SomeStringProperty =
DependencyProperty.RegisterAttached(
"SomeString",
typeof(string),
typeof(MyCustomPropertyCollection),
new FrameworkPropertyMetadata(string.Empty));
public static void SetSomeString(UIElement element, string value) {
element.SetValue(SomeStringProperty, value);
}
public static string GetSomeString(UIElement element) {
return (string)element.GetValue(SomeStringProperty);
}
}
Style.DataTrigger
<DataTrigger Binding="{Binding Path=(local:MyCustomPropertyCollection.SomeString),
RelativeSource={RelativeSource Self}}"
Value="{x:Static sys:String.Empty}">
...
</DataTrigger>
usage:
<Button x:Name="btnPosition"
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding PositionFilterCommand}"
Content="{l:Translate position}"
local:MyCustomPropertyCollection.SomeString="{Binding SelectedPositions}"
Style="{StaticResource NewButtonStyle}" />
3 - Normal Dependency Property
custom Button
class:
public class MyButton : Button {
public static readonly DependencyProperty SomeStringProperty =
DependencyProperty.Register(
"SomeString",
typeof(string),
typeof(MyButton),
new FrameworkPropertyMetadata(string.Empty));
public string SomeString {
get {
return (string)GetValue(SomeStringProperty);
}
set {
SetValue(SomeStringProperty, value);
}
}
}
Style in xaml not only needs DataTrigger
updated but Style
definition too.
so switch
<Style x:Key="NewButtonStyle" TargetType="{x:Type Button}">
to
<Style x:Key="NewButtonStyle" TargetType="{x:Type local:MyButton}">
Style.DataTrigger
<DataTrigger Binding="{Binding Path=SomeString,
RelativeSource={RelativeSource Self}}"
Value="{x:Static sys:String.Empty}">
...
</DataTrigger>
usage:
<local:MyButton x:Name="btnPosition"
Grid.Row="0"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding PositionFilterCommand}"
Content="{l:Translate position}"
SomeString="{Binding SelectedPositions}"
Style="{StaticResource NewButtonStyle}" />
Tag
approach is frowned upon. "Attached Property" is easier to implement but isn't as clear of a indicator of dependencies as a custom class with a normal DP and AP also gets way overused. Take your pick for what you'd prefer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With