如何覆盖没有x:Key的全局样式,或者将命名样式应用于所有类型目标控件?

49

我声明了一个风格,我想将其应用于项目中的所有按钮,这个风格存储在ResourceDictionary中:

<Style TargetType="StackPanel">
    <Setter Property="Orientation" Value="Horizontal" />
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
</Style>

现在,在某个窗口中,我想继承这个样式但添加一个值:

<Style TargetType="StackPanel"> 
    <Setter Property="Margin" Value="5"/>
</Style>
问题在于它并没有继承全局样式,为了进行继承,我必须给全局样式分配一个键:

问题在于它没有从全局样式中继承,为了继承,我需要给全局样式分配一个键:

<Style TargetType="StackPanel" x:Key="StackPanelStyle" />

然后在窗口的 XAML 中继承(或/和覆盖 - 可选)它:

<Style TargetType="StackPanel" BasedOn="StackPanelStyle" />

问题在于,如果你分配了一个键,它并不是全局的,你必须在每个窗口/范围上调用它。

解决方法应该是以下两者之一(我是否漏掉了其他东西?):

  1. 有一个带有键的全局样式,自动应用于整个应用程序中的所有目标控件。
  2. 一种引用ResourceDictionary级别未命名样式且不覆盖它的方法。

我考虑过在命名样式旁重新声明样式(在ResourceDictionary中),实际上这是起作用的:

<!--In the ResourceDictionary-->
<Style x:Key="StackPanelStyle" TargetType="StackPanel">
    <Setter Property="Orientation" Value="Horizontal" />
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<!--In the app.xaml-->
<Style TargetType="StackPanel" BasedOn="{StaticResource StackPanelStyle}"/>
<!--In the window/page scope-->
<Style TargetType="StackPanel" BasedOn="{StaticResource StackPanelStyle}"/

但我正在寻找比愚蠢地重新声明所有样式更好的东西。

3个回答

80

试试这个:

<Style TargetType="{x:Type StackPanel}" BasedOn="{StaticResource {x:Type StackPanel}}">
  <!-- ... -->
</Style>

我已经在App.xaml中的ResourceDictionary中声明了我的基础样式,如果像这样在特定的窗口中覆盖它们,通常会起作用。


2
这个在Silverlight中怎么样? - MSNetDev
除非我设置x:Key,否则这个解决方案对我无效:<Style TargetType="{x:Type StackPanel}" BasedOn="{StaticResource {x:Type StackPanel}}" x:Key="MyStackPanel">。有没有不设置x:Key的解决方案? - chriga
@chriga 你尝试过将键设置为 x:Key="{x:Type StackPanel}" 吗?(至少如果你正在使用WPF,对于Silverlight我不确定) - Botz3000
@Botz3000 当我明确使用 x:Key="{x:Type StackPanel}" 时,我得到了相同的结果。 - chriga
@chriga 我不知道。你是在使用Silverlight还是Windows Store应用的XAML?资源是否在范围内?它应该适用于普通的桌面WPF。 - Botz3000
显示剩余7条评论

1
在全局资源字典中,您需要定义一个基础样式并赋予其一个键。该基础样式是针对类型的,这种类型是您想要应用该样式的所有类型的基础。然后,您需要定义基于上述基础样式并针对所需类型的样式。
<Style
    x:Key="upDownBaseStyle"
    TargetType="{x:Type Control}">
    <Setter
      Property="Margin"
      Value="2" />
    <Setter
      Property="HorizontalAlignment"
      Value="Stretch" />
    <Setter
      Property="VerticalAlignment"
      Value="Center" />
  </Style>

  <Style
    TargetType="{x:Type xceed:IntegerUpDown}"
    BasedOn="{StaticResource upDownBaseStyle}">
  </Style>

  <Style
    TargetType="{x:Type xceed:DoubleUpDown}"
    BasedOn="{StaticResource upDownBaseStyle}">
  </Style>

现在,这两种最后的样式都适用于应用程序中的所有IntegerUpDown和DoubleUpDown控件,而无需提及键。
因此,基本规则是:基本样式必须具有键来引用它,而派生样式可能没有键,因此它们可以仅通过目标类型应用。

0
我建议您可能在寻找一个主样式或行为方案,通常可以通过创建用户控件来实现。如果您创建了一个新的按钮控件,并将您的“全局”样式应用于它,那么您在任何地方使用该控件时,只需添加任何“新”样式或在需要时覆盖样式即可。
如果您还没有创建用户控件,那么它们很容易实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接