3
votes

I have a series of TextBlocks to which I want apply a Style and DataTrigger. The only difference is that the Binding is to a different property in the view model for each one.

Here is a simplified version of one of the TextBlocks with the Style and DataTrigger "built in".

        <TextBlock Text="Is development">
            <TextBlock.Style>
                <Style TargetType="{x:Type TextBlock}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsDevelopmentIsDirty}"
                                      Value="True">
                            <Setter Property="FontWeight"
                                    Value="Bold" />
                            <Setter Property="FontStyle"
                                    Value="Italic" />
                            <Setter Property="Foreground"
                                    Value="{StaticResource SCB_TardisBlue}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>

So, in the preceding example, the "IsDevelopmentIsDirty" binding would be different for each TextBlock.

I'm just not having the greatest luck in finding the best way to consolidate this Style into one declaration that can be used by the entire series of TextBlocks.

Is there a way to assign the style and the property to which the DataTrigger should bind? If not, what is a way to do this? My thanks in advance.

2

2 Answers

3
votes

If you want to trigger same style change based on different property depending on the TextBlock you can use proxy property. This is assuming that it will a boolean property, or one that can be converted to boolean.

Solution 1

In simplest solution you can use Tag property

<TextBlock Text="Is development" Tag="{Binding IsDevelopmentIsDirty}" >
   <TextBlock.Style>
      <Style TargetType="{x:Type TextBlock}">
         <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Value="True">
               <Setter Property="FontWeight" Value="Bold" />
               <Setter Property="FontStyle" Value="Italic" />
               <Setter Property="Foreground" Value="{StaticResource SCB_TardisBlue}" />
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </TextBlock.Style>
</TextBlock>

From inside of the Style you trigger on Tag property being true and then on the outside you can bind Tag property to whatever you want. Of course this Style can then be extracted to some resource dictionary.

Solution 2

Another solution for example if you need more the one property is to create attached properties

public static class AttachedProperties
{
    public static readonly DependencyProperty ChangeStyleProperty = DependencyProperty.RegisterAttached("ChangeStyle", typeof(bool), typeof(AttachedProperties));

    public static bool GetChangeStyle(DependencyObject d)
    {
        return (bool)d.GetValue(ChangeStyleProperty);
    }

    public static void SetChangeStyle(DependencyObject d, bool value)
    {
        d.SetValue(ChangeStyleProperty, value);
    }
}

and then follow same scenario as with Tag

<TextBlock Text="Is development" prop:AttachedProperties.ChangeStyle="{Binding IsDevelopmentIsDirty}" >
   <TextBlock.Style>
      <Style TargetType="{x:Type TextBlock}">
         <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(prop:AttachedProperties.ChangeStyle)}" Value="True">
               <Setter Property="FontWeight" Value="Bold" />
               <Setter Property="FontStyle" Value="Italic" />
               <Setter Property="Foreground" Value="{StaticResource SCB_TardisBlue}" />
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </TextBlock.Style>
</TextBlock>
0
votes

Declare the style at the top of the page like this

<Window.Resources>
  <Style x:Key="MyTextBlockStyle" TargetType="{x:Type TextBlock}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsDevelopmentIsDirty}"
                                  Value="True">
                        <Setter Property="FontWeight"
                                Value="Bold" />
                        <Setter Property="FontStyle"
                                Value="Italic" />
                        <Setter Property="Foreground"
                                Value="{StaticResource SCB_TardisBlue}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
</Window.Resources>

Then the TextBlock should be like this

<TextBlock Text="Text" Style="{StaticResource MyTextBlockStyle}"/>