Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Foreground Color of Entire Window

Tags:

c#

wpf

I'd like to set the foreground (text) color to all of my elements You'd think this would be easy, but it's not...

<Window Foreground="Red">    <Label Content="Test"/>    <Label Content="Test"/>    <CheckBox Content="Checkbox"/> </Window> 

This has no effect... The only way I can get this to work is if I set the Foreground property on each one of the elements specifically. And this gets annoying if you have hundreds of elements, etc.

Maybe you know of a way?

like image 328
Shai UI Avatar asked Mar 16 '11 15:03

Shai UI


People also ask

What is foreground color in computer?

Foreground colour is the beginning colour of a default gradient applied by the gradient tool. Background colour is the colour you apply with the eraser tool and is the ending colour of the default gradient.

What is the difference between foreground and background color?

The foreground controls what color your brush or pencil will be, while the background color erases any added color and replaces it with the background color, which is white by default.


1 Answers

This is because such controls as Label and CheckBox override the Foreground property in their styles.

Below is an example a typical logical tree of elements that shows how the value specified on the Window level travels down the tree:

Window (Red [Local])    -> Grid (Red [Inherited])       -> ListBox (Red [Inherited])          -> ListBoxItem (Red [Inherited])             -> StackPanel (Red [Inherited])                -> Label (Black [Style])                  -> TextBlock (Black [Inherited])               -> TextBlock (Red [Inherited]) 

In square brackets the source of the value is shown.

As you can see the inheritance breaks on the Label itself because it has the Foreground property set in its default style:

<Style x:Key="{x:Type Label}"        TargetType="{x:Type Label}">     <Setter Property="Foreground"             Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>     ... </Style> 

As a workaround for this we can use the following trick. Define the default style for such controls (as Label) in the application (in App.xaml or in the Window inself). And in that default style override the Foreground property to set a relative source binding to the nearest ancestor of the control that still has the desired value:

<Style TargetType="{x:Type Label}">     <Setter Property="Foreground"             Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/> </Style>  <Style TargetType="{x:Type CheckBox}">     <Setter Property="Foreground"             Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/> </Style> 

After that our tree will look like this:

Window (Red [Local])    -> Grid (Red [Inherited])       -> ListBox (Red [Inherited])          -> ListBoxItem (Red [Inherited])             -> StackPanel (Red [Inherited])                -> Label (Red [Binding to StackPanel.(TextElement.Foreground)])                  -> TextBlock (Red [Inherited])               -> TextBlock (Red [Inherited]) 

As you can see, our binding restores the inheritance.

Such styles need to be defined for each element that overrides the Foreground property in its style. As @Duane suggested, to not duplicate the binding in each style the BasedOn capability can be used:

<Style x:Key="ForegroundInheritanceFixStyle"        TargetType="Control">     <Setter Property="Foreground"             Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/> </Style>  <Style TargetType="{x:Type Label}"        BasedOn="{StaticResource ForegroundInheritanceFixStyle}"> </Style>  <Style TargetType="{x:Type CheckBox}"        BasedOn="{StaticResource ForegroundInheritanceFixStyle}"> </Style> 

Hope this helps.

like image 83
Pavlo Glazkov Avatar answered Sep 18 '22 00:09

Pavlo Glazkov