在前一个Post中,曾提到将要重点研究Dependency属性的三个方面:变化通知;属性值的继承;支持多个提供对象。下面,我将分别就这三个内容进行简单地说明。
【变化通知】
在任何时候,只要Dependency属性的值发生了变化,WPF可以自动地根据属性的元数据触发不同的行为。前面提到过:Dependency属性最大的特点就是内建的变化通知功能。这种内建变化通知所提供的最值得注意的就是属性触发器(Property Trigger),就是它使用我们不需要编写任何的程序代码就能在属性变化使执行自定义行为。请看下面XAML编码的一个属性触发器例子:
<Trigger Property=”IsMouseOver” Value=”True”>
<Setter Property=”Foreground” Value=”Blue”/>
</Trigger>
它的功能就是在属性值IsMouseOver变为True的时,将属性Foreground的值设置为Blue。而且,它会在IsMouseOver变为False时自动将Foreground的值设置为原来的值。就是这样简单的三行代码完成了我们曾经需要多个函数、变量才能实现的功能。
使用属性触发器时需要注意:触发器默认适用于每个类对象。 而且,在WPF 3.0中由于人为的限制,Property Trigger将不能应用在单独的元素。只能应用在某个Style对象之中。因此,如果想在某个单独对象上实现Property Trigger。必须用如下的XAML进行封装:
<Button MinWidth=”75” Margin=”10”>
<Button.Style>
<Style TargetType=”{x:Type Button}”>
<Style.Triggers>
<Trigger Property=”IsMouseOver” Value=”True”>
<Setter Property=”Foreground” Value=”Blue”/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
OK
</Button>
【属性值继承】
属性值继承是指在设置逻辑树某个结点元素的属性后,它的所有之结点都继承这个属性值(当然,前提是子元素必须支持这个属性)。我们仍然利用闲话WPF之八中的一个例子进行说明:
<Window FontSize=”30”>
<StackPanel>
<Label>LabelText</Lable>
</StackPanel>
</Window>
我们修改了Window是FontSize属性为30。通过实际观察将发现它的子元素Label的FontSize也变为了30。注意这里的StackPanel是一个容器元素,它本身并不支持FontSize属性。
现在我们给上面的Window添加一个状态栏。XAML代码如下:
<Window ......>
<StackPanel>
<Label>LabelText</Lable>
<StatusBar>This is a Statusbar</StatusBar>
</StackPanel>
</Window>
这时你会发现:虽然StatusBar支持这个FontSize这个属性,它也是Window的子元素,但是它的字体大小却没有变化。为什么呢?因为并不是所有的元素都支持属性值继承。还存在如下两种例外的情况:
1、部分Dependency属性在用Register注册时可以指定Inherits为不可继承。
2、如果有其他更高优先级方法设置了其他的值。(关于优先级的介绍且看下面分解。)
部分控件如StatusBar、Menu和Tooptip内部设置它们的字体属性值以匹配当前系统的设置。这样用户通过控制面板可以修改它们的外观。这种方法存在一个问题:StatusBar等截获了从父元素继承来的属性,并且不影响其子元素。比如,如果我们在StatusBar中添加了一个Button。这个Button的字体属性会因为StatusBar的截断没没有改变,将保留其默认值。
附加说明:属性值继承的最初设计只适用于元素Tree,现在已经进行多个方面的扩展。比如,值可以传递下级看起来像Children,但在逻辑或者视觉Tree中并不是Children的某些元素。这些伪装的子元素可以是触发器、属性的值,只要它是从Freezable继承的对象。对于这些内容没有很好的文档说明。我们只需要能使用就行不必过多关心。
本文转自赖仪灵博客园博客,原文链接:http://www.cnblogs.com/YilingLai/archive/2006/12/24/601994.html,如需转载请自行联系原作者。