这是因为Label 和CheckBox 等控件在其样式中覆盖了Foreground 属性。
下面是一个典型的元素逻辑树示例,它显示了在Window 级别上指定的值如何沿树向下传播:
Window (Red [Local])
-> Grid (Red [Inherited])
-> ListBox (Red [Inherited])
-> ListBoxItem (Red [Inherited])
-> StackPanel (Red [Inherited])
-> Label (Black [Style])
-> TextBlock (Black [Inherited])
-> TextBlock (Red [Inherited])
方括号中显示了值的来源。
正如您所见,Label 本身的继承中断,因为它的默认样式中设置了 Foreground 属性:
<Style x:Key="{x:Type Label}"
TargetType="{x:Type Label}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
...
</Style>
作为一种解决方法,我们可以使用以下技巧。在应用程序中(在 App.xaml 或 Window inself 中)定义此类控件的默认样式(如 Label)。并在该默认样式中覆盖 Foreground 属性,以将相对源绑定设置为仍具有所需值的控件的最近祖先:
<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>
之后我们的树将如下所示:
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])
如您所见,我们的绑定恢复了继承。
需要为覆盖其样式中的Foreground 属性的每个元素定义此类样式。正如@Duane 建议的那样,为了不重复每种样式的绑定,可以使用BasedOn 功能:
<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>
希望这会有所帮助。