DataTrigger Binding in WPF Style

.net, c#, mvvm, wpf

Solution

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.

Problem

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> ```

Original source