Search code examples
c#wpf.net-5

ContentStringFormat never changes by Setter Property in DataTrigger


In my user control I want to have label displaying Text from resource depending on viewmodel property Location value and with different format. I implemented it by defining DataTrigger for each Location value

<Style x:Key="LocationValueHelper" TargetType="{x:Type Label}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Location}" Value="HomeViewModel">
            <Setter Property="Content" Value="" />
            <Setter Property="ContentStringFormat" Value="{}{0}???"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Location}" Value="FirstViewModel">
            <Setter Property="ContentStringFormat" Value="{}{0}+++"/>
            <Setter Property="Content" Value="{localization:LanguageResource ResourceKey=First}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Location}" Value="SecondViewModel">
            <Setter Property="ContentStringFormat" Value="{}{0}---"/>
            <Setter Property="Content" Value="{localization:LanguageResource ResourceKey=Second}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Location}" Value="ThirdViewModel">
            <Setter Property="ContentStringFormat" Value="{}{0}***"/>
            <Setter Property="Content" Value="{localization:LanguageResource ResourceKey=Third}" />
        </DataTrigger>
    </Style.Triggers>
</Style>


<Label Foreground="White" HorizontalAlignment="Center" FontSize="40" Style="{StaticResource LocationValueHelper}" />

The problem is that format never changes from the first one (???) - HomeViewModel selected first - although text changing works.

I have

Home???
First???
Second???
Third???

instead of

Home???
First+++
Second---
Third***

Solution

  • There are a lot of discussions, using Labels and ContentStringFormat does not work like expected or desired:

    The reason seems to be the template based implementation under the hood, since the content also could contain other data than strings. To solve your problem, my proposal is to use a TextBlock, which works quite smooth like this:

    <StackPanel>
        <CheckBox IsChecked="{Binding MyFlag}"/>
        <TextBlock HorizontalAlignment="Center" FontSize="40">
            <TextBlock.Style>
                <Style TargetType="{x:Type TextBlock}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding MyFlag}" Value="False">
                            <Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}+++'}" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding MyFlag}" Value="True">
                            <Setter Property="Text" Value="{Binding Path=MyText, StringFormat='{}{0}???'}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </StackPanel>