首页 文章

如何扩展而不是覆盖WPF样式

提问于
浏览
24

我想在我的应用程序中使用自定义主题,据我所知,我可以通过使用资源字典并在App.xaml中引用它来实现此目的 . 样式将覆盖默认值,如下所示:

<Style TargetType="{x:Type Label">
    <Setter Property="Foreground" Value="Green" />
</Style>

现在我猜我的默认标签样式是用相同的值覆盖但我的所有标签字体都是绿色 . 当我想再次在某个地方设置一个标签时,问题就出现了 . 当我想像我这样更改网格中的其他属性时

<Grid.Resources>
    <Style TargetType="{x:Type Label">
        <Setter Property="FontSize" Value="28" />
    </Style>
</Grid.Resources>

我的网格中的所有标签都会丢失其前景色并再次出现默认值(我是否在上一步中覆盖了默认值?) . 经过一些尝试,我发现要正确地做到这一点,我必须添加另一个属性 Style 声明 BasedOn={StaticResource {x:Type Label}}" ,它的工作原理 . 这对我来说有点奇怪,因为现在我将不得不在整个应用程序中重复相同的BasedOn代码,这不是样式的工作原理 - 这应该自动完成!例如,在HTML中CSS样式是继承和合并的,在WPF中它们被替换...

请注意,当我不使用任何样式控件时,仍然可以从somehwere(System Themes?)中获取它们的外观 . 我怎么能告诉他们在其他地方寻找默认值,所以如果没有任何额外的样式代码,他们会认为默认情况下它们应该是绿色的?

有什么方法可以自动设置BasedOn属性吗?或者也许有更好的做到这一点?

2 回答

  • 10

    我有同样的问题 . 我使用了Zack的答案并对其进行了改进,如果您没有指定样式,则仍会考虑覆盖的默认值 . 它基本上就是你在ResourceDictionary中所做的但只有一次 .

    <Window x:Class="TestWpf.RandomStuffWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Random Stuff Window">
      <Window.Resources>
        <ResourceDictionary>
          <!-- Default Label style definition -->
          <Style TargetType="{x:Type Label}">
            <Setter Property="Foreground" Value="Green" />
          </Style>
          <!-- Extending default style -->
          <Style TargetType="{x:Type Label}" 
                 x:Key="LargeGreenForegroundLabel" 
                 BasedOn="{StaticResource {x:Type Label}}">
            <Setter Property="FontSize" Value="28" />
          </Style>
        </ResourceDictionary>
      </Window.Resources>
      <StackPanel>
        <Button Click="Button_Click">Click</Button>
        <Label Content="GreenForegroundLabel" /> <!-- Uses default style -->
        <Label Style="{StaticResource LargeGreenForegroundLabel}" 
               Content="LargeGreenForegroundLabel" />
      </StackPanel>
    </Window>
    
  • 26

    Wpf具有不同级别的样式,按全局>局部顺序应用 . 直接在控件上设置的样式将覆盖全局样式集,如示例中所示 . 我试图找到一个控件查找其样式的所有不同位置的列表,但我目前找不到一个 . 据我所知,您必须使用BasedOn属性继承样式,而不是使用您在本地设置的样式完全覆盖该样式的属性 .

    下面是一个包含基于另一个样式的样式的资源字典的示例,因此您不必反复重复 BasedOn 绑定,只需在要具有该样式的特定元素上设置样式即可 .

    <Window x:Class="TestWpf.RandomStuffWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Random Stuff Window">
      <Window.Resources>
        <ResourceDictionary>
          <Style TargetType="{x:Type Label}" 
                 x:Key="GreenForegroundLabel">
            <Setter Property="Foreground" Value="Green" />
          </Style>
          <Style TargetType="{x:Type Label}" 
                 x:Key="LargeGreenForegroundLabel" 
                 BasedOn="{StaticResource GreenForegroundLabel}">
            <Setter Property="FontSize" Value="28" />
          </Style>
        </ResourceDictionary>
      </Window.Resources>
      <StackPanel>
        <Button Click="Button_Click">Click</Button>
        <Label Style="{StaticResource GreenForegroundLabel}" 
               Content="GreenForegroundLabel" />
        <Label Style="{StaticResource LargeGreenForegroundLabel}" 
               Content="LargeGreenForegroundLabel" />
      </StackPanel>
    </Window>
    

相关问题