0
votes

In my WPF application, I have to keep on updating TextBlock background based on user conditions. TextBlock style is defined in App.xaml. If the background is too dark (Green/Blue) I want to set the foreground to white else black. How can I achieve this? I explored following two options:

  1. Via DataTriggers: In App.xaml:

       <Style TargetType="TextBlock">             
         <Setter Property="FontSize" Value="14"/>
         <Setter Property="FontStyle" Value="Normal"/>
         <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Background,PresentationTraceSources.TraceLevel=High}" Value="White">
                <Setter Property="Foreground" Value="Maroon"/>
            </DataTrigger>
         </Style.Triggers>
     </Style>
    

This doesn't seem to work. I never see an update in textblock's foreground property. While debugging, I see the following for the binding: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

System.Windows.Data Warning: 72 : RelativeSource.Self found TextBlock (hash=61003640) System.Windows.Data Warning: 78 : BindingExpression (hash=6398298): Activate with root item TextBlock (hash=61003640) System.Windows.Data Warning: 107 : BindingExpression (hash=6398298): At level 0 using cached accessor for TextBlock.Background: DependencyProperty(Background) System.Windows.Data Warning: 104 : BindingExpression (hash=6398298): Replace item at level 0 with TextBlock (hash=61003640), using accessor DependencyProperty(Background) System.Windows.Data Warning: 101 : BindingExpression (hash=6398298): GetValue at level 0 from TextBlock (hash=61003640) using DependencyProperty(Background): SolidColorBrush (hash=58614288) System.Windows.Data Warning: 80 : BindingExpression (hash=6398298): TransferValue - got raw value SolidColorBrush (hash=58614288) System.Windows.Data Warning: 89 : BindingExpression (hash=6398298): TransferValue - using final value SolidColorBrush (hash=58614288) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

What is "SolidColorBrush (hash=58614288)"? Is it the Hex color code or hascode for the object of type SolidColorBrush?

  1. Using IValueConverter: Have not tried it since I don't want to convert one value to another but change a UIElement's property based on some other property change. Also, wouldn't converters will give a performance hit since almost all UIElements use TextBlock internally to display data?

I have already looked at the following thread: Change TextBlock foreground color based on the background. It didnt help my case. Any help is highly appreciated.

Thanks,

RDV

A little more about my application:

When my application starts, my TextBlocks have default background color. All the Textblock styling is stored in a ResourceDictionary which is stored in a different solution. I have only one ResourceDictionary in App.xaml of my application:

<Application x:Class="MySolution"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/ResourcesSolution;component/Resources/GenericStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

FontWeight, FontStyle, even Foreground etc. are correctly picked up from here. But these are static properties. On certain user action, I change the TextBlock's background color at runtime but sometimes that makes text unreadable like Black text on Green background. I can definitely bind the foreground color as well when background color is changing, but in that case I would have to do that binding in all the views. Instead I want to have a global style take care of this job so that even if I forget to bind the foreground color, correct color is automatically picked.

I have a big application and performance is a major concern. That's why I am hesitant to use converters and was looking for some xaml based solutions as this is just a condition based issue.

1
SolidColorBrush is a single color Brush that can be applied to Backgrounds/Foregrounds etc. Can you show your Xaml style.sa_ddam213
I have also tried binding to Background.Color.RDV

1 Answers

1
votes

I tested my code by setting Background on only TextBlock control and I could see the following style triggers working as expected when declared as global style sheet:

<Style TargetType="TextBlock">
        <Setter Property="FontSize" Value="12"/>
        <Setter Property="FontStyle" Value="Italic"/>
        <Style.Triggers>
            <Trigger Property="Background" Value="White">
                <Setter Property="Foreground" Value="Aqua"/>
            </Trigger>
            <Trigger Property="Background.Color" Value="Transparent">
                <Setter Property="Foreground" Value="BlueViolet"/>
            </Trigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Background}" Value="White">
                <Setter Property="Foreground" Value="Maroon"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Background.Color}" Value="#FF008000">
                <Setter Property="Foreground" Value="Blue"/>
            </DataTrigger>

        </Style.Triggers>
    </Style>

However, I did not notice the behavior initially because I assumed that the Button's content, which is internally represented by TextBlock, should also use the TextBlock's style trigger (it is picking up TextBlock's FontSize and FontStyle defined in global style).

I think this is related to ContentPresenter issue and should be addressed in a different thread.

Thanks,

RDV