我想将前景(文本)颜色设置为我的所有元素 你认为这很容易,但不是......
<Window Foreground="Red">
<Label Content="Test"/>
<Label Content="Test"/>
<CheckBox Content="Checkbox"/>
</Window>
这没有任何效果......我能让这个工作的唯一方法就是我专门为每个元素设置Foreground属性。如果你有数百个元素等,这会很烦人。
也许你知道一种方式?
答案 0 :(得分:26)
这是因为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
inself中)。并且在该默认样式中覆盖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>
希望这有帮助。
答案 1 :(得分:6)
遗憾的是,样式在WPF中的工作方式不能在父类上创建通用样式,并且它适用于子类控件。
您可以做的一件事是创建一个基本样式,该基本样式使用您要设置的属性(如ContentControl)定位基本类型,然后为每个基于该样式的控件创建特定样式。这是一个例子:
<Window>
<Window.Resources>
<Style x:Key="BaseContentControlStyle" TargetType="{x:Type ContentControl}">
<Setter Property="Foreground" Value="Red" />
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseContentControlStyle}" />
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource BaseContentControlStyle}" />
</Window.Resources>
<StackPanel>
<Label Content="Test"/>
<Label Content="Test"/>
<CheckBox Content="Checkbox"/>
</StackPanel>
</Window>
希望这有帮助。
编辑:
您可以使用下面的Pavlo方法来恢复继承,并使其更容易使用,如下所示:
<Window.Resources>
<Style x:Key="BaseContentControlStyle" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/>
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseContentControlStyle}" />
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource BaseContentControlStyle}" />
</Window.Resources>
至少那时你不必在任何地方复制相同的setter代码(BTW,我认为TextBlock默认继承;没有覆盖的默认样式)。
答案 2 :(得分:0)
是的,在wpf中这并不容易。但你可以这样试试
<StackPanel>
<StackPanel.Resources>
<Style x:Key="CommonStyle">
<Setter Property="TextElement.Foreground" Value="Red" />
</Style>
</StackPanel.Resources>
<Label Content="Test" Style="{StaticResource CommonStyle}" />
<Label Content="Test" Style="{StaticResource CommonStyle}"/>
<CheckBox Content="Checkbox" Style="{StaticResource CommonStyle}"/>
</StackPanel>
答案 3 :(得分:0)
如果您要配置数百个单独的元素,那肯定会很烦人,但我假设您不会有数百个不同的类型元素。
在这种情况下,您可以做的一件事是为您的类型创建样式,并在那里设置前景色。
理想情况下,这可能位于ResourceDictionary
中,每个样式都会引用一个共同的前景颜色,例如
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="appForegroundColor" Color="Red" />
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{StaticResource appForegroundColor}" />
</Style>
<!-- Create styles for Element Types here -->
</ResourceDictionary>
然后将此资源字典应用于需要它的窗口,例如:
<Window ...>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TextBlock Text="Foo" />
</Grid>
</Window>