如何将一个样式应用于一个类及其后代?

时间:2010-11-25 15:44:55

标签: .net wpf xaml button styles

我想将以下样式应用于从ButtonBase

派生的所有控件
<Style
    TargetType="{x:Type ButtonBase}">
    <Setter
        Property="Cursor"
        Value="Hand" />
</Style>

但它只适用于给定的类,而不适用于它的后代。如何实现我的目标?

2 个答案:

答案 0 :(得分:4)

这不起作用,因为当元素没有显式指定样式时,WPF通过调用FindResource来找到它的样式,使用元素的类型作为键。您创建了一个密钥为ButtonBase的样式并不重要的事实:WPF会找到密钥为ButtonToggleButton的样式并使用它。

基于继承的查找方法将使用元素的类型查找样式,然后在未找到元素类型的样式时使用基类型(并继续运行,直到找到样式或命中{{1 }})。问题是只有在找不到匹配项时才有效 - 即如果FrameworkElement没有默认样式,那当然就是。

你可以做两件事。一个是做Jens建议的,使用样式的Button属性来实现自己的样式层次结构。但是,这有点烦人,因为你必须为每一种类型定义一种风格;如果不这样做,将使用该类型的默认WPF样式。

另一种方法是使用实​​现此查找行为的BasedOn。像这样:

StyleSelector

你可以创建一个这样的实例,给它一组样式,然后将它附加到任何public class InheritanceStyleSelector : StyleSelector { public InheritanceStyleSelector() { Styles = new Dictionary<object, Style>(); } public override Style SelectStyle(object item, DependencyObject container) { Type t = item.GetType(); while(true) { if (Styles.ContainsKey(t)) { return Styles[t]; } if (t == typeof(FrameworkElement) || t == typeof(object)) { return null; } t = t.BaseType; } } public Dictionary<object, Style> Styles { get; set; } }

ItemsControl

答案 1 :(得分:3)

这确实似乎是造型系统的限制。

面对这个问题,我宣布了一些基本风格,并为我关心的每个后代“子风格”。

<Style x:Key="ButtonBaseStyle" TargetType="{x:Type ButtonBase}">
    <!-- Style stuff -->
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonBaseStyle}">
    <!-- Additional style stuff for button only -->
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource ButtonBaseStyle}">
    <!-- Additional style stuff for toggle button only -->
</Style>
<!-- more ButtonBase descendants here  -->