Change Notification
无论何时,只要DP的值发生了变化,WPF都会根据属性的元数据(在注册DP时的设置)自动触发一系列操作。这些操作可以使让元素UI重新呈现,更新当前布局或者刷新数据绑定等等。其中最有意思的就是属性触发器(property trigger)了。当属性值发生变化时,属性触发器可以在不编写程序代码的情况下执行您的自定义行为。
举例来说,您希望鼠标悬浮在List 3.1中的按钮上时,按钮的文字变成蓝色。如果不使用属性触发器,您可以在按钮的MouseEnter事件和MouseLeave事件中进行处理:
<Button MouseEnter=”Button_MouseEnter” MouseLeave=”Button_MouseLeave”
MinWidth=”75” Margin=”10”>Help</Button>
<Button MouseEnter=”Button_MouseEnter” MouseLeave=”Button_MouseLeave”
MinWidth=”75” Margin=”10”>OK</Button>
使用c#实现两个事件处理函数:
// Change the foreground to blue when the mouse enters
the button
void Button_MouseEnter(object sender, MouseEventArgs e)
{
Button b = sender as Button;
if (b != null) b.Foreground = Brushes.Blue;
}
// Restore the
foreground to black when the mouse exits the button
void
Button_MouseLeave(object sender, MouseEventArgs e)
{
Button b = sender as Button;
if (b != null) b.Foreground = Brushes.Black;
}
有了属性触发器,您就可以在XAML中实现相同的功能了,代码相当简洁:
<Trigger Property=”IsMouseOver”
Value=”True”>
<Setter Property=”Foreground” Value=”Blue”/>
</Trigger>
这个属性触发器作用与Button的IsMouseOver属性。当MouseEnter触发的那一刻,属性值为True,MouseLeave事件触发时变为false。注意,您不需要关心IsMouseOver变为false时Foreground属性是否会变回黑色,这个操作由WPF自动完成。
唯一的窍门是如何将属性触发器应用到Button中。不幸的是,由于3.0版本中WPF的人为限制,您无法将属性触发器直接应用到元素中。必须将它放到Style对象内,我们会在第十章深入介绍属性触发器。如果您想尝试属性触发器的使用,可以将之前的代码进行如下改进:
<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一共支持三种触发器。属性触发器只是其中的一种,另一种是数据触发器(data trigger),这种触发器可以应用于所有的.NET属性(而不仅仅是dp),第十章将会介绍。最后一种是事件触发器(event trigger)可以让您声明指定的行为,当routed event触发时就会执行这些行为。事件触发器总是用于调用动画或者声音,第十三章将会介绍。
唯一的窍门是如何将属性触发器应用到Button中。不幸的是,由于3.0版本中WPF的人为限制,您无法将属性触发器直接应用到元素中。必须将它放到Style对象内,我们会在第十章深入介绍属性触发器。如果您想尝试属性触发器的使用,可以将之前的代码进行如下改进:
<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一共支持三种触发器。属性触发器只是其中的一种,另一种是数据触发器(data trigger),这种触发器可以应用于所有的.NET属性(而不仅仅是dp),第十章将会介绍。最后一种是事件触发器(event trigger)可以让您声明指定的行为,当routed event触发时就会执行这些行为。事件触发器总是用于调用动画或者声音,第十三章将会介绍。
WARNING
Don’t be fooled by an
element’s Triggers collection!
FrameworkElement的Triggers属性是可写可读的,它是TriggerBase(之前介绍的三种trigger的基类)类的集合。所以表面上看起来可以Triggers里可以存放属性触发器。不幸的是,3.0版本的WPF中,这个属性只能接收事件触发器。因为WPF小组没有时间去实现支持存放属性触发器的功能。如果在Triggers属性中放置了属性触发器(或者数据触发器),程序会在运行是抛出异常(指在程序代码中。如果在XAML里写入了属性触发器,编译时就会报错,译者注)。