FrameowrkElement, Style, DataTemplate和ControlTemplate都有一个Triggers集合。
Trigger分三类:
► Property trigger: dependency property改变时触发。对应的Trigger类。比较Property和Value的值,如果相同,则触发,如不同不触发或撤消更改。常见的例子是用bool值作触发条件,但是请记得,只要Property和Value值相同就会触发,并不一定必须使用如IsMouseOver这样的bool值。
► Data trigger:普通的.net属性改变时触发。对应的DataTrigger类。使用 DataTrigger,可以在数据对象的属性值与指定的 Value 匹配时设置属性值。例如,在显示 Employee 对象列表时,可能希望前景色根据每个 Employee 的当前出勤情况而变化。(例如,用紫色前景色显示当前正在休假的 Employee。) 在有些情况下,创建转换器或使用 DataTemplateSelector 可能会更适合。有关更多信息,请参见 数据模板化概述。
Data trigger适用于数据绑定的情况。
► Event trigger: 由事件触发。对应的是EventTrigger类。与上面两个Trigger不一样的是,Event trigger不会在条件不满足时撤消操作。
请注意,使用 EventTrigger 时,需要选择不会影响控件内在行为的事件。控件(例如 Button 或 TextBox)执行有关用户输入事件(如鼠标单击和键盘事件)的特定操作。例如,如果要对按钮进行样式设置,并尝试将 MouseDown 事件设置为 EventTrigger 的 RoutedEvent,则永远也不会应用 EventTrigger,因为该事件将首先经过按钮的处理。可以改用 PreviewMouseDown 事件或其他事件。
由于以上三个Trigger都是继承自TriggerBase类,所以也都有EnterActions和ExitActions属性,分别记录Trigger变为活动状态时及变为非活动状态时的TriggerAction 对象的集合,而这两个属性是对Event trigger不适用的。
Property trigger:
<Style x:Key="buttonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="10"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
<Setter Property="FontSize" Value="22"/>
<Setter Property="Background" Value="Purple"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="RenderTransformOrigin" Value=".5,.5"/>
</Style>
Data trigger:
<StackPanel Width="200"> <StackPanel.Resources> <Style TargetType="{x:Type TextBox}"> <Style.Triggers> <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="disabled"> <Setter Property="IsEnabled" Value="False"/> </DataTrigger> </Style.Triggers> <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/> </Style> </StackPanel.Resources> <TextBox Margin="3"/> </StackPanel>
Event Trigger:
<Style TargetType="Rectangle"> <Setter Property="Width" Value="50" /> <Setter Property="Height" Value="50" /> <Setter Property="Margin" Value="20" /> <Setter Property="HorizontalAlignment" Value="Left" /> <Style.Triggers> <EventTrigger RoutedEvent="MouseEnter"> <BeginStoryboard> <Storyboard> <DoubleAnimation To="300" Duration="0:0:1.5" AccelerationRatio="0.10" DecelerationRatio="0.25" Storyboard.TargetProperty="(Canvas.Width)" /> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="MouseLeave"> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="0:0:1.5" AccelerationRatio="0.10" DecelerationRatio="0.25" Storyboard.TargetProperty="(Canvas.Width)" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Style.Triggers> </Style>
“或”逻辑很简单,只要对同一对象上设置多个trigger就可以
<Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="RenderTransform"> <Setter.Value> <RotateTransform Angle="10"/> </Setter.Value> </Setter> <Setter Property="Foreground" Value="Black"/> </Trigger> <Trigger Property="IsFocused" Value="True"> <Setter Property="RenderTransform"> <Setter.Value> <RotateTransform Angle="10"/> </Setter.Value> </Setter> <Setter Property="Foreground" Value="Black"/> </Trigger> </Style.Triggers>
“与”操作时,需要用到MultiTrigger和MultiDataTrigger(两者也都继承于TriggerBase),两者的区别就像Trigger和DataTrigger一样。“与”的判断是通过Conditions对象来判断的,只有Conditions中计算出来都为true时才能触发:
MultiTrigger:
<Style.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Background" Value="#EEEEEE" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="HasItems" Value="false" /> <Condition Property="Width" Value="Auto" /> </MultiTrigger.Conditions> <Setter Property="MinWidth" Value="120"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="HasItems" Value="false" /> <Condition Property="Height" Value="Auto" /> </MultiTrigger.Conditions> <Setter Property="MinHeight" Value="95"/> </MultiTrigger> </Style.Triggers>
MultriDataTrigger:
<Window.Resources> <c:Places x:Key="PlacesData"/> <Style TargetType="ListBoxItem"> <Style.Triggers> <DataTrigger Binding="{Binding Path=State}" Value="WA"> <Setter Property="Foreground" Value="Red" /> </DataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding Path=Name}" Value="Portland" /> <Condition Binding="{Binding Path=State}" Value="OR" /> </MultiDataTrigger.Conditions> <Setter Property="Background" Value="Cyan" /> </MultiDataTrigger> </Style.Triggers> </Style> <DataTemplate DataType="{x:Type c:Place}"> <Canvas Width="160" Height="20"> <TextBlock FontSize="12" Width="130" Canvas.Left="0" Text="{Binding Path=Name}"/> <TextBlock FontSize="12" Width="30" Canvas.Left="130" Text="{Binding Path=State}"/> </Canvas> </DataTemplate> </Window.Resources> <StackPanel> <TextBlock FontSize="18" Margin="5" FontWeight="Bold" HorizontalAlignment="Center">Data Trigger Sample</TextBlock> <ListBox Width="180" HorizontalAlignment="Center" Background="Honeydew" ItemsSource="{Binding Source={StaticResource PlacesData}}"/> </StackPanel>