1
votes

I have several TextBlocks in my UserControl that I want to change to become Bold and have a Red font when a Property is triggered. The thing is that each of them are changed by different properties. I saw a solution here with Tags, but couldn't quite get it to work for me. I apologize if this is a duplicate, but I couldn't find any solution that solved my problem.

My Style looks like this:

<Style x:Key="TextBlockTrigger" TargetType="{x:Type TextBlock}">
  <Style.Triggers>
    <Trigger Property="Tag" Value="true">
      <Setter Property="FontWeight" Value="Bold"/>
      <Setter Property="Foreground" Value="Red"/>
    </Trigger>
  </Style.Triggers>
</Style>

And this is the TextBlock I'm trying to use it on:

<TextBlock Name="TextBlock1" x:Uid="TextBlock1" Text="This text should become bold and Red"
Style="{StaticResource TextBlockTrigger}" Tag="{Binding Path=TriggerProperty, UpdateSourceTrigger=PropertyChanged}"/> 

I added a button with a codebehind function that reads the Tag, and a breakpoint shows that Tag is set to true, but the text is still regular black.

TriggerProperty is set by a function call in the View Constructor, after InitializeComponent:

public MyWindow()
{
  InitializeComponent();
  UpdateServerProperties();
}

public void UpdateServerProperties()
{
    //other code
    if(ServerValue == true)
    {
        TriggerProperty = true;
        OnPropertyChanged("TriggerProperty");
    }
}

It's a bit simplified, but the actual code is overly complicated, but results in the same thing. ServerValue gets a value, and I have confirmed TriggerProperty does get updated to true.

2
Do you set the TriggerProperty property dynamically? Do you implement INotifyPropertyChanged?mm8

2 Answers

2
votes

The Tag property has an object type. Xaml has no way of knowing that true represents a bool value, so it just assumes you meant it to be a string. Assuming you are setting Tag to a boolean value, your Trigger is evaluating Equals(true, "true"), so the condition fails.

Try using {x:Static} to point to some constant boolean value. I keep a KnownBoxes class around for this sort of thing:

public static class KnownBoxes
{
    public static readonly object True = true;
    public static readonly object False = false;

    // ... more common values ...
}

These values are easily referenced from Xaml, e.g., {x:Static ns:KnownBoxes.True}.

Alternatively, you could use the element syntax:

<Trigger Property="Tag">
  <Trigger.Value>
    <s:Boolean xmlns:s="clr-namespace:System;assembly=mscorlib">True</s:Boolean>
  </Trigger.Value>
  <Setter Property="FontWeight" Value="Bold"/>
  <Setter Property="Foreground" Value="Red"/>
</Trigger>

Or you could set Tag to the string "true", though that may cause some confusion when someone else works on your code :).

1
votes

If you set TriggerProperty to true dynamically at runtime, the class where this property is defined should implement the INotifyPropertyChanged interface and raise the PropertyChanged event for the trigger to trigger.

If you set the Tag property to a hard-coded value of true, your sample markup should work as expected:

<TextBlock Name="TextBlock1" x:Uid="TextBlock1" Text="This text should become bold and Red"
           Style="{StaticResource TextBlockTrigger}" Tag="true"/>

You should also set the Value property to a typed bool value in your Style:

<Style x:Key="TextBlockTrigger" TargetType="{x:Type TextBlock}"
       xmlns:s="clr-namespace:System;assembly=mscorlib">
    <Style.Triggers>
        <Trigger Property="Tag">
            <Trigger.Value>
                <s:Boolean>True</s:Boolean>
            </Trigger.Value>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="Foreground" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>