Question

I have some DatTriggers which set text color for ListView items. If I use TextBox as ItemTemplate for the ListView it works perfectly. But it doesn't work if I use TextBlock.

This code:

<Style TargetType="TextBox">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Level,Mode=OneWay}"
                     Value="{x:Static Common:LoggingLevel.Error}">
            <Setter Property="Foreground"
                    Value="Red" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Level,Mode=OneWay}"
                     Value="{x:Static Common:LoggingLevel.Warning}">
            <Setter Property="Foreground"
                    Value="Orange" />
        </DataTrigger>
    </Style.Triggers>
</Style>

...

<ListView ItemsSource="{Binding Entries}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Text,Mode=OneWay}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

produces properly colored list of messages.

While this code:

<Style TargetType="TextBlock">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Level,Mode=OneWay}"
                     Value="{x:Static Common:LoggingLevel.Error}">
            <Setter Property="Foreground"
                    Value="Red" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Level,Mode=OneWay}"
                     Value="{x:Static Common:LoggingLevel.Warning}">
            <Setter Property="Foreground"
                    Value="Orange" />
        </DataTrigger>
    </Style.Triggers>
</Style>

...

<ListView ItemsSource="{Binding Entries}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Text,Mode=OneWay}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

renders all messages with default black foreground color.

Was it helpful?

Solution

Implicit styles are applied within templates to elements which inherit from System.Windows.Controls.Control and since TextBlock inherits directly from FrameworkElement it will not apply. To make it work you must give your Style x:Key and assign style explicitly to your TextBlock or define your style within TextBlock

UPDATE:
I should also mention, to cover the topic, that there is a way to apply implicit Style to all TextBlocks. If you put it in Application.Resources it will apply to all TextBlocks across whole application. In this case it would cause some major performance issues and potentially other errors, which is probably why Microsoft decided to protect these basic elements from accidentally using complicated, implicit styles on them. Not everyone realise that basically every piece of text that you see in your Window ends up as TextBlock.

OTHER TIPS

Provide the key to the Style and apply it with the TextBlock as shown below:

<Style TargetType="TextBlock" x:Key="txtID">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Level,Mode=OneWay}" Value="{x:Static Common:LoggingLevel.Error}">
            <Setter Property="Foreground" Value="Red" />
        </DataTrigger>

        <DataTrigger Binding="{Binding Level,Mode=OneWay}" Value="{x:StaticCommon:LoggingLevel.Warning}">
            <Setter Property="Foreground" Value="Orange" />
        </DataTrigger>
    </Style.Triggers>
</Style>

<ListView ItemsSource="{Binding Entries}">
     <ListView.ItemTemplate>
         <DataTemplate>
             <TextBlock Text="{Binding Text,Mode=OneWay}" Style="{DynamicResource txtID}"/>
         </DataTemplate>
     </ListView.ItemTemplate>
</ListView>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top