设置整个窗口的前景色

for*_*yez 23 c# wpf

我想将前景(文本)颜色设置为我的所有元素你会认为这很容易,但它不是......

<Window Foreground="Red">
   <Label Content="Test"/>
   <Label Content="Test"/>
   <CheckBox Content="Checkbox"/>
</Window>
Run Code Online (Sandbox Code Playgroud)

这没有任何影响......我可以让它工作的唯一方法是,如果我专门为每个元素设置Foreground属性.如果你有数百个元素等,这会很烦人.

也许你知道一种方式?

Pav*_*kov 27

这是因为这样的控件LabelCheckBox覆盖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])
Run Code Online (Sandbox Code Playgroud)

在方括号中,显示值的来源.

正如您所看到的,继承会Label自行中断,因为它具有Foreground以其默认样式设置的属性:

<Style x:Key="{x:Type Label}"
       TargetType="{x:Type Label}">
    <Setter Property="Foreground"
            Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    ...
</Style>
Run Code Online (Sandbox Code Playgroud)

作为解决方法,我们可以使用以下技巧.Label在应用程序中定义此类控件(如)的默认样式(在App.xaml或Windowinself中).并且在该默认样式中覆盖该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>
Run Code Online (Sandbox Code Playgroud)

之后,我们的树将如下所示:

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])
Run Code Online (Sandbox Code Playgroud)

如您所见,我们的绑定恢复了继承.

需要为每个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>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


Dua*_*ane 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>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

编辑:

您可以使用下面的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>
Run Code Online (Sandbox Code Playgroud)

至少那时你不必在任何地方复制相同的setter代码(BTW,我认为TextBlock默认继承;没有覆盖的默认样式).