为什么使用触发器?
美工设计了很多效果,并把其设计成样式展现(很大程度上我们应该认为Style也是一种资源),而作为程序员的我们不应该只是简单的拿style拼凑的效果,根据程序的逻辑和用户的操作来动态的展现效果才是我们能发挥它对界面渲染的更好途径。Trigger就给我们提供了很好的途径去结合这些元素。
触发器,从某种意义上来说它也是一种Style,因为它包含有一个Setter集合,并根据一个或多个条件执行Setter中的属性改变。因为复用的缘故,Styles是放置触发器的最好位置。但对于每个FrameworkElement来说都有Triggers集合,你也可以放在Triggers集合里。触发器有三种类型:
属性触发器Property Trigger:当Dependency Property的值发生改变时触发。
数据触发器Data Trigger: 当普通.NET属性的值发生改变时触发。
事件触发器Event Trigger: 当路由时间被触发时调用。
下面我们来看看触发器是如何使用的
1.属性触发器(property Trigger)
下面这个触发器是当鼠标悬停在按钮上时,按钮发生变化,这里也能看出触发器是由Trigger标识的。
property Trigger
<UserControl.Resources>
<Style x:Key="buttonMouseOver" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="10"></RotateTransform>
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
<Setter Property="Background" Value="#FF0CC030" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="4*"/>
</Grid.RowDefinitions>
<Button Style="{StaticResource buttonMouseOver}"/>
</Grid>
2. 数据触发器Data Trigger
数据触发器和属性触发器除了面对的对象类型不一样外完全相同。数据触发器是来检测非依赖属性------也就是用户自定义的.NET属性-----的值发生变化时来触发并调用符合条件的一系列Setter集合。
下边的示例演示了在绑定的ListBox里如果某个User对象符合某种特点(Role=Admin),则以突出方式显示这个对象。这里就用了DataTrigger,因为我们需要检测的是User对象的属性Role,这个对象是自定义的非可视化对象并且其属性为普通.NET属性。
Data Trigger
<Page.Resources>
<clr:Users x:Key="myUsers" />
<DataTemplate DataType="{x:Type clr:User}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</Page.Resources>
<StackPanel>
<ListBox Width="200"
ItemsSource="{Binding Source={StaticResource myUsers}}" />
</StackPanel>
主要的部分定义在了Style中,其针对的是每个ListBox的项,当其被绑定的数据的属性Role为Admin时,突出显示:
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Role}" Value="Admin">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
3.事件触发器Event Trigger
事件触发器,顾名思义是在某个事件被触发时来调用这个触发器的相关操作。因为WPF提供了用XAML来标记对象,事件等,所以其提供了一些在普通.NET开发中看似没用的属性例如IsMouseOver, IsPressed等,这是为了XAML来用的,使其可以很方便的通过某个属性来判断状态,也方便了Property Trigger的应用。而作为事件触发器来说,它所做的事情和Property Trigger类似,不过是它的内部不能是简单的Setter集合,而必须是TriggerAction的实例。
<Button Margin=
"
15
"
Width=
"
200
"
Name=
"
myButton
"
>
Click Me to Animate Drop Shadow
!
<Button.BitmapEffect>
<DropShadowBitmapEffect x:Name=
"
myDropShadowBitmapEffect
"
Color=
"
Black
"
ShadowDepth=
"
0
"
/>
</Button.BitmapEffect>
<Button.Triggers>
<EventTrigger RoutedEvent=
"
Button.Click
"
>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty=
"
Margin
"
Duration=
"
0:0:0.5
"
From
=
"
50,50,50,50
"
To=
"
0,0,50,50
"
AutoReverse=
"
True
"
/>
<DoubleAnimation Storyboard.TargetName=
"
myDropShadowBitmapEffect
"
Storyboard.TargetProperty
=
"
ShadowDepth
"
From
=
"
0
"
To=
"
30
"
Duration=
"
0:0:0.5
"
AutoReverse=
"
True
"
/>
<DoubleAnimation Storyboard.TargetName=
"
myDropShadowBitmapEffect
"
Storyboard.TargetProperty
=
"
Softness
"
From
=
"
0
"
To=
"
1
"
Duration=
"
0:0:0.5
"
AutoReverse=
"
True
"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>