Это связано с тем, что такие элементы управления, как 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>
В качестве обходного пути для этого мы можем использовать следующий прием.Определите стиль по умолчанию для таких элементов управления (например, Label
) в приложении (в файле App.xaml или в самом файле Window
).И в этом стиле по умолчанию переопределите свойство 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>
Надеюсь, это поможет.