WPF中的Dependency Property(2)

在前一个Post中,我们举例说明了如何实现一个Dependency Property,而在这一个Post中,我们将重点关注Dependency Property的变化通知能力。

我们知道,无论何时,只要Dependency Property的值改变了,WPF就会自动依据属性元数据的设定触发一系列的动作。而这些设定,就是我们事先在定义Dependency Property时已经定义过的,如前一个Post中的FontSize property

metadata.AffectsMeasure = true;

metadata.Inherits = true;

metadata.IsNotDataBindable = false;

metadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

AffectsMeasure标志表明属性的改变是否会造成控件尺寸的重新计算(这也需要控件进行重绘);Inherits标志表明属性值是否允许被继承;IsNotDataBindable标志表明属性是否允许进行数据绑定;DefaultUpdateSourceTrigger标志表明更新数据绑定的时机。

因此,上面提到的,Dependency Property的改变会触发的一系列动作包括:重新呈现适当的元素、更新当前布局、刷新数据绑定等。

内建的变化通知最有趣的特征之一是属性触发器,它可以在属性值改变时执行自定义的动作,而不用添加任何过程式代码。

假设我们要实现这样的功能:当鼠标移动到Button上时,将文本的颜色变为Blue;而离开时恢复。如果没有属性触发器,我们可能这样来实现:

前台代码:

<Button Content="Click" Width="100" Height="50"

         VerticalAlignment="Bottom" HorizontalAlignment="Center"

     MouseEnter="ButtonOnMouseEnter" MouseLeave="ButtonOnMouseLeave"/>

后台代码:

private void ButtonOnMouseEnter(object sender, MouseEventArgs e)

{

    Button btn = sender as Button;

    if (btn != null)

    {

        btn.Foreground = Brushes.Blue;

    }

}

 

private void ButtonOnMouseLeave(object sender, MouseEventArgs e)

{

    Button btn = sender as Button;

    if (btn != null)

    {

        btn.Foreground = Brushes.Black;

    }

}

然而,有了属性触发器,我们完全可以在前台XAML中完成相同的行为,而且代码相当少:

<Trigger Property="IsMouseOver" Value="True">

    <Setter Property="Foreground" Value="Blue"/>

</Trigger>

它的功能是:当IsMouseOver属性变成True时,改变Foreground属性为Brushes.Blue;而当IsMouseOver属性变成False时,设置Foreground属性为原来的值(此处不需要写代码,WPF自动完成)。IsMouseOver属性的改变能让属性触发器得到通知,这就是变化通知能力的一种体现。

当我们把Trigger赋给Button时,遇到了一点困难,不能把属性触发器直接应用到控件上。在WPF 3.0中,由于人为限制,Trigger只能在Style对象内部应用。因此,可以在<Window.Resources>中添加或者在<Button.Style>中添加。

我们在<Window.Resources>中添加作示例:

<Window.Resources>

    <Style TargetType="{x:Type Button}">

        <Style.Triggers>

            <Trigger Property="IsMouseOver" Value="True">

                <Setter Property="Foreground" Value="Blue"/>

            </Trigger>

        </Style.Triggers>

    </Style>

</Window.Resources>

WPF除了支持属性触发器外,还支持另外两种触发器——数据触发器、事件触发器。这些将会在其他的Post中详细说明。

注意:不要被元素的Triggers集合所愚弄!

FrameworkElementTriggers属性是一个可读写的TriggerBase项(三个触发器类型的通用基类)集合,因此,它是把属性触发器添加给元素最简单的方式。不幸的是,这个集合只能包括事件触发器,因为WPF团队没有时间来实现这种支持。如果你尝试添加一个属性触发器到Triggers属性中,将导致运行时抛出一个异常。

posted on 2009-01-05 20:11  xirihanlin  阅读(855)  评论(0编辑  收藏  举报