是使用嵌套的标签创建对象,作为每个 Setter
对象的一部分)
BasedOn TargetType
通过该属性可以创建继承自(并且可以有选择地进行重写)其他样式设置的更加复杂的样式 该属性标识应用样式的元素的类型。通过该属性可以创建只影响特定类型元素的样式,并且还可 以创建能够为恰当的元素类型自动执行动作的样式
现在, 您已经看到了一个使用样式的基本示例, 这为进一步深入分析样式模型做好了准备。
12.1.1
创建样式对象
在上一个示例中,样式对象是在窗口级别定义的,之后在窗口的两按钮中重用该样式。尽 管这是一种常见的
设计,但也不是唯一的选择。 如果希望创建更精细的目标样式, 可以使用包容器的 Resources 集合定义样式, StackPanel 如 面板或 Grid 面板。如果希望在应用
程序中重用样式,可以使用应用程序的 Resources 集合定义 样式。这些是更
常用的方法。 严格地讲,不需要同时使用样式和资源。例如,可以通过直接填充特定按钮的样式集合来 定义样式,如下所示:
A Customized Button
上面的代码虽然可以工作, 但显然不是很有用。 因为现在无法在其他元素之间共享该样式。 如果只是使用样式设置一些属性(如本示例),就不值得使用这种方法,因为直接设置属性 更加容易。然而,如果正在使用样式的其他特性,并且只希望将它应用到单个元素,这一方法 有时会有用。例如,可以使用该方法为一个元素关联事件处理程序。通过该方法还可以修改部 分元素控件模板(对于这种情况,需要使用 Setter.TargetName 属性,在元素的内部为特定组件应 用一个设置器,如
列表框中的滚动条按钮。有关该技术的更多内容将在第 15 章中学习)。
291
WPF 编程宝典— 使用 C# 2008 和.NET 3.5(第 2 版) —
12.1.2
设置属性
正如所介绍的,每个 Style 对象包装了一个 Setter 对象的集合。每个 Setter 对象设置元素的 单个属性。唯一的限制是设置器只能改变依赖项属性—— 不能修改其他属性。 在某些情况下,不能使用简单的特性字符串设置属性值。例如,不能使用简单的字符串设 置 ImageBrush 对象(如第 11 章中使用的显示平铺模式的图像画刷)。对于这种情况,可以使用 熟悉的 XAML 技巧,使用嵌套的元素代替特性。下面是一个示例:
提示: 如果希望在多个样式中(或在同一样式的多个设置器中)重用相同的图像画刷,可以将其定 义为资源,然后再在样式中使用资源。 为了标识希望设置的属性,需要提供类和属性的名称。然而,需要的类名不一定是定义属 性的类名。 也可以是继承了准备设置的属性的派生类。 例如, 考虑如下版本的 BigFontButtonStyle 样式,它使用 Button
类的引用代替了 Control 类的引用:
如果将上面的示例(见图 12-1)替换为这个样式,可以得到完全相同的结果。那么这两者之 间到底有什么区别呢?对于这种情况,区别在于 WPF 对可能包含相同的 FontFamily 属性、 FontSize 属性以及 FontWeight 属性,但又不继承自 Button 类的类的处理方式。例如,如果为 Label 控件使用了该版本的 BigFontButtonStyle 样式, 就没有效果。 WPF 简单地略过这三个属性, 因为不会应用它们。但如果使用原来的那个样式,字体属性就会影响 Label 控件,因为 Label 类继承自 Control 类。 提示: WPF 忽略属性而不应用它们的这一事实,意味着使用样式设置的属性,不必是在应用样式 的元素中定义的属性。例如,如果设置 ButtonBase.IsCancel 属性,只有当为按钮设置样式时才 会有效果。 在 WPF 中还存在这样一种情况,在元素框架层次中的多个位置定义了同一个属性。例如, 在 Control 类和 TextBlock 类中都定义了全部的字体属性(如 FontFamily 属性)。如果创建应用到
292
第 12 章
样
式
TextBlock 对象以及应用到继承自 Control 类的元素的样式,可以按如下方式创建标记:
然 而 , 这 样 不 会 得