Quantcast
Channel: Windows Presentation Foundation (WPF) forum
Viewing all articles
Browse latest Browse all 18858

Change foreground color dynamically based on background color

$
0
0

Problem domain: In my WPF application, I change background of lot of UI controls like Button or ListItems dynamically based on data they contain. The background is changed either when the control is loaded or based on use action/data received.

Problem statement: If the background is too dark (Green/Blue) I want to set the foreground to white else black.

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

Solutions tried: To keep it simple, I am explaining what I tried for a simple wpf button:

<UserControl.Resources><Style x:Key="NoChromeButton" TargetType="{x:Type Button}"><Setter Property="Background" Value="{Binding Background}"/><Setter Property="OverridesDefaultStyle" Value="True"/><Setter Property="BorderThickness" Value="1"/><Setter Property="BorderBrush" Value="White"/><Setter Property="HorizontalContentAlignment" Value="Center"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Padding" Value="1"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><Grid x:Name="Chrome" 
                          Background="{TemplateBinding Background}" 
                          SnapsToDevicePixels="true"
                          HorizontalAlignment="Stretch"><TextBlock 
                        Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          Margin="{TemplateBinding Padding}" 
                                          Background="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                        Style="{StaticResource MyTextBlockStyle}"/></Grid><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="Black"/></Trigger><Trigger Property="Background" Value="White"><Setter Property="Foreground" Value="Aqua"/></Trigger><Trigger Property="Background" Value="Transparent"><Setter Property="Foreground" Value="BlueViolet"/></Trigger><Trigger Property="Background" Value="Green"><Setter Property="Foreground" Value="Blue"/></Trigger><Trigger Property="Background" Value="Yellow"><Setter Property="Foreground" Value="Red"/></Trigger><Trigger Property="Background" Value="Red"><Setter Property="Foreground" Value="Yellow"/></Trigger><Trigger Property="Background" Value="Black"><Setter Property="Foreground" Value="DarkSeaGreen"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter><Style x:key="MyTextBlockStyle" 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" Value="Transparent"><Setter Property="Foreground" Value="BlueViolet"/></Trigger><Trigger Property="Background" Value="Green"><Setter Property="Foreground" Value="Blue"/></Trigger><Trigger Property="Background" Value="Yellow"><Setter Property="Foreground" Value="Red"/></Trigger><Trigger Property="Background" Value="Red"><Setter Property="Foreground" Value="Yellow"/></Trigger><Trigger Property="Background" Value="Black"><Setter Property="Foreground" Value="DarkSeaGreen"/></Trigger></Style></UserControl.Resources>

When button is created in the XAML:

<Button Content="{Binding Name}" Style="{StaticResource NoChromeButton}"/>

Also, I would like to point out a couple of things in the above style:

  1. If I would have used ContentPresenter instead of TextBlock inside the Grid named Chrome, background property was not set on the ContentPresenter and when I snooped the UI, I found that the ContentPresenter has TextBlock whose Background was always set to Default and hence no styletriggers were applied to the TextBlock. Also, this TextBlock's background valuesource is Default.

On the other hand, when I use TextBlock directly inside the Grid named Chrome, I can set its background explicitly to Grid's Background which is set to Button's Background. Snooping reveals that now TextBlock's Background ValueSource is ParentTemplate.

  1. Button picks up MyTextBlockStyle while displaying its content.

  2. Style triggers for Button or TextBlock were never triggered unless I did mouse over the button which changes the button's background to Black and propagates this value down to TextBlock background changing the TextBlock's foreground color to DarkSeaGreen.

  3. Also, changing the button's background in snoop utility while application is running, triggers the Style Triggers.

Questions:

  1. Why none of the Style triggers work for Background property whereas they work for IsMouseOver property?

  2. What I am doing wrong?

  3. Any solution for this?

Thanks,

RDV


Viewing all articles
Browse latest Browse all 18858

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>