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 ...
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>

本文深入分析了Windows应用中,当窗口前景色被设置为不同于默认值时,子控件如何继承其前景色的问题。通过实例展示了Label和CheckBox等控件如何覆盖其样式中的前景色属性,并解释了这种行为背后的原因。文章还提供了一个工作-around方案,即在应用程序级别定义控件的默认样式,并使用相对源绑定来恢复继承关系。此外,讨论了当尝试更改某些数据控件的默认设置时,颜色变化不受影响的问题,以及如何解决这个问题。
2298

被折叠的 条评论
为什么被折叠?



