WPF - Setting foreground color of Entire window

46 篇文章 0 订阅

You might as well as I would suppose that if we just set the foreground of a window to something different from its original color, then the whole controls from the window might change as well?
well this is not true, consider this example. 

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

 

 

the reason as pointed by Pavlo Glazkov is as such ...

Pavlo Glazkov 写道
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 theLabelitself because it has theForegroundproperty 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:

 

 

<StyleTargetType="{x:Type Label}"><SetterProperty="Foreground"Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/></Style><StyleTargetType="{x:Type CheckBox}"><SetterProperty="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 Foregroundproperty 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"><SetterProperty="Foreground"Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/></Style><StyleTargetType="{x:Type Label}"BasedOn="{StaticResource ForegroundInheritanceFixStyle}"></Style><StyleTargetType="{x:Type CheckBox}"BasedOn="{StaticResource ForegroundInheritanceFixStyle}"></Style>

 

 

And because of this inheritance relationship, I found there is a problem when I tried to change the default settings for some data control, the change is not affected, it was because the container element is no modified for its fore/ground, background color.  

so, e.g.

 

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dx="clr-namespace:DevExpress.Xpf.Core;assembly=DevExpress.Xpf.Core.v12.1"
    xmlns:vm="clr-namespace:RiskLayoutExample.ViewModels"
    xmlns:dxg="clr-namespace:DevExpress.Xpf.Grid;assembly=DevExpress.Xpf.Grid.v12.1"
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
    >
  <DataTemplate DataType="{x:Type vm:RiskDataViewModel}">
    <dx:BackgroundPanel>
      <DataGrid
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          ItemsSource="{Binding RiskData}"
                  >
        <DataGrid.Resources>
                      <Style TargetType="TextBlock"  x:Key="{x:Type TextBlock}" >
                      </Style>
                      <Style TargetType="TextBoxBase" x:Key="{x:Type TextBoxBase}" 
                             >
                      </Style>
                      <Style TargetType="TextBox"  x:Key="{x:Type TextBox}" />
                      <Style TargetType="DataGridCell" x:Key="{x:Type DataGridCell}">
                      </Style>
                      <!-- .. -->
        </DataGrid.Resources>

        <DataGrid.Columns>
          <DataGridTextColumn
              Header="Book"
              Binding="{Binding Book}"
              IsReadOnly="True"
                          >
          </DataGridTextColumn>
          <!-- ... -->
        </DataGrid.Columns>
      </DataGrid>
    </dx:BackgroundPanel>
  </DataTemplate>
</ResourceDictionary>

 

 

the text color of the DataGridCell does not change, so I hvae to change the foreground and background of the dxd:BackgroundPanel

So I have to supply the color of the containing element. 

    <dx:BackgroundPanel
      Foreground="White"
      Background="Black">
   </dx:BackgroundPanel>

 

 

References:

Setting Foreground Color of Entire Window

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值