在应用程序的生命周期中,用户界面中对象的状态会发生改变。通常以面向用户的术语来表述状态。例如,按钮的“鼠标悬停”状态或菜单项的“按下”状态。这两个示例状态是分别使用 UIElement.IsMouseOver 属性和 MenuItem.IsPressed 属性在对象上实现的。
但对用户而言,这些属性的值及其代表的状态不是可见的。 IsMouseOver 和 IsPressed 都不是可视属性。为了观察这些属性,非可视属性的更改必须触发可视属性(如 Background 或 Opacity )的更改。例如,原本平整的按钮会在变为“鼠标悬停”状态后凹下去;菜单项也会在“按下”时更改背景颜色。
除了更改状态以外,对象还会引发事件。例如,当指针越过按钮边界时,将引发 MouseEnter 和 MouseLeave 事件。同样地,事件本身也没有可视外观,因此它必须触发可视属性的更改,才能被用户注意到。
可以在文档的根元素中或者在应用于控件的样式中创建触发器(和动画时间线)。例如,可以修改按钮的样式,以便在按钮的“按下”和“变换”状态更改时,按钮的外观能发生细微变化。应用了该样式的任何按钮都会有相同的行为。有关示例,请参阅动手试验:向按钮添加动画。
有两种触发器:
| 属性触发器 | 通过此机制,一个属性的更改会在另一个属性中触发即时或动态更改。 |
| 事件触发器 | 通过此机制,事件会在属性中触发动态更改 |
这里就简单的使用一个示例,展示一下属性触发:这里使用Button作为示例,改写了Button的模板,使用IsMouseOver和IsPressed属性改变控件的背景颜色。
- <UserControl.Resources>
- <Style x:Key="BtnStyle" TargetType="{x:Type Button}">
- <Setter Property="Height" Value="35"/>
- <Setter Property="HorizontalAlignment" Value="Stretch"/>
- <Setter Property="FontSize" Value="14"/>
- <Setter Property="Foreground" Value="#dddddd"/>
- <Setter Property="Background" Value="#454a64"/>
- <Setter Property="HorizontalContentAlignment" Value="Center"/>
- <Setter Property="VerticalContentAlignment" Value="Center"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type Button}">
- <Border x:Name="bd" Background="{TemplateBinding Background}" CornerRadius="5">
- <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
- <Image x:Name="img_path" Source="/WPFControlStyle;component/Resources/Images/status.png" Width="20" Height="20" Margin="5 0" Stretch="Fill"/>
- <TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" FontSize="{TemplateBinding FontSize}" Foreground="{TemplateBinding Foreground}"/>
- StackPanel>
- Border>
-
- <ControlTemplate.Triggers>
- <DataTrigger Binding="{Binding IsShow}" Value="False">
- <Setter Property="Visibility" Value="Collapsed" TargetName="img_path"/>
- DataTrigger>
- <Trigger Property="Tag" Value="LeftBottom">
- <Setter Property="CornerRadius" Value="0,0,0,5" TargetName="bd"/>
- Trigger>
- <Trigger Property="Tag" Value="RightBottom">
- <Setter Property="CornerRadius" Value="0,0,5,0" TargetName="bd"/>
- Trigger>
- ControlTemplate.Triggers>
- ControlTemplate>
- Setter.Value>
- Setter>
- <Style.Triggers>
- <Trigger Property="IsMouseOver" Value="True">
- <Setter Property="Background" Value="#007dc0"/>
- Trigger>
- <Trigger Property="IsPressed" Value="True">
- <Setter Property="Background" Value="Orange"/>
- Trigger>
- Style.Triggers>
- Style>
- UserControl.Resources>
调用样式代码
- <StackPanel Margin="10" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
- <Button Style="{StaticResource BtnStyle}" Tag="LeftBottom" Width="120" Height="45" HorizontalAlignment="Center" VerticalAlignment="Center" Content="触发器测试" Click="Button_Click"/>
- <Button Margin="5 0" Style="{StaticResource BtnStyle}" Tag="RightBottom" Width="120" Height="45" HorizontalAlignment="Center" VerticalAlignment="Center" Content="触发器测试"/>
- StackPanel>
后台代码:通过数据触发器触发,控制按钮中图标的显示或者隐藏
- public partial class ButtonStyleUserControl : UserControl, INotifyPropertyChanged
- {
- public ButtonStyleUserControl()
- {
- InitializeComponent();
- this.DataContext = this;
- IsShow = false;
- }
- private bool isShow = false;
- public bool IsShow
- {
- get { return isShow; }
- set
- {
- isShow = value;
- OnPropertyChanged("IsShow");
- }
- }
- public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
- protected void OnPropertyChanged(string propertyName)
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
- }
- }
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- IsShow = !IsShow;
- }
- }
执行代码运行效果图:

当鼠标移动在按钮上时,触发IsMouseOver属性,按钮背景色变为蓝色;

当鼠标在按钮上,按下时,触发IsPressed属性,按钮背景色变为橙色;

点击第一个按钮后,数据触发器触发,显示了按钮中的图标。

扩展:
通常,一个属性与一组相应的事件相对应,您可以决定是设计一个属性触发器,还是设计两个事件触发器。例如,可以使用 IsMouseOver 属性触发器,或者成对使用 MouseEnter 和 MouseLeave 事件触发器来实现相同的效果。应尽可能使用属性触发器,而在不得不使用事件触发器时才使用它(例如,未使用样式或模板时)。
**************************************************************************************************************