在应用程序的生命周期中,用户界面中对象的状态会发生改变。通常以面向用户的术语来表述状态。例如,按钮的“鼠标悬停”状态或菜单项的“按下”状态。这两个示例状态是分别使用 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 事件触发器来实现相同的效果。应尽可能使用属性触发器,而在不得不使用事件触发器时才使用它(例如,未使用样式或模板时)。
**************************************************************************************************************