WPF中有個主題,就是以聲明方式擴充代碼的功能。當使用樣式、資源或資料綁定時,将發現即使不使用代碼,也能完成不少工作。
觸發器是另一個實作這種功能的例子。使用觸發器,可自動完成簡單的樣式改變,而這通常需要使用樣闆事件處理邏輯。例如,當屬性發生變化時可以進行響應,并自動調整樣式。
觸發器通過Style.Triggers集合連結到樣式。每個樣式都可以有任意多個觸發器,而且每個觸發器都是System.Windows.TriggerBase的派生類的執行個體。下表列出了WPF中的選項。
表 繼承自TriggerBase的類

通過使用FrameworkElement.Triggers集合,可直接為元素應用觸發器,而不需要建立樣式。但這存在一個相當大的缺陷。這個Triggers集合隻支援事件觸發器(并非技術上的原因造成了該限制,隻是因為WPF團隊沒時間實作該特性,将來的版本中可能包含該特性)。
一、簡單觸發器
可為任何依賴項屬性關聯簡單觸發器。例如,可通過響應Control類的IsFocused、IsMouseOver以及IsPressed屬性的變化,建立滑鼠懸停效果和焦點效果。
每個簡單觸發器都制定了正在監視的屬性,以及正在等待的屬性值。當該屬性值出現時,将應用存儲在Trigger.Setters集合中的設定器(但不能使用更複雜的觸發器邏輯。例如,比較某個值以檢視其是否處于某個範圍,或執行某種計算等。對于這些情況,最好使用事件處理程式)。
下面的觸發器等待按鈕獲得鍵盤焦點,當擷取焦點時會将前景色設定為深紅色:
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
</Style.Setters>
<Style.Triggers>
<Trigger Property="Control.IsFocused" Value="True">
<Setter Property="Control.Foreground" Value="DarkRed" />
</Trigger>
</Style.Triggers>
</Style>
觸發器的優點是不需要翻轉它們而編寫任何邏輯。隻要停止應用觸發器,元素就會恢複到正常外觀。在該例中,這意味着隻要使用者使用Tab鍵讓按鈕失去焦點,按鈕就會恢複為通常的灰色背景。
可建立一次應用于同一進制素的多個觸發器。如果這些觸發器設定不同的屬性,着鮮紅情況就不會出現混亂。然而,如果多個觸發器修改同一屬性,那麼最後的觸發器将有效。
例如,分析下面的觸發器,這些觸發器根據控件是否焦點、滑鼠是否懸停在控件上,以及是否單擊了控件,對控件進行修改:
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
</Style.Setters>
<Style.Triggers>
<Trigger Property="Control.IsFocused" Value="True">
<Setter Property="Control.Foreground" Value="DarkRed" />
</Trigger>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.Foreground" Value="LightYellow" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Trigger>
<Trigger Property="Button.IsPressed" Value="True">
<Setter Property="Control.Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
顯然,滑鼠可能懸停在目前具有焦點的按鈕上。這不會出現問題,因為這兩個觸發器修改不同的屬性。但如果單擊按鈕,就有兩個不同的觸發器試圖設定前景色。現在,針對Button.IsPressed屬性的觸發器勝出,因為它是最後一個觸發器,這與哪個觸發器首先發生并無完全決定了最終效果。
如果希望建立隻有當幾個條件都為真時才激活的觸發器,可使用MultiTrigger。這種觸發器提供了一個Conditions集合,可通過該集合定義一系列屬性和值得組合。在下面的示例中,隻有按鈕具有焦點而且滑鼠懸停在該按鈕上時,才會應用格式化資訊:
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
</Style.Setters>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Control.IsFocused" Value="True"/>
<Condition Property="Control.IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Control.Foreground" Value="DarkRed" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
對于這種情況,不必關心聲明條件的順序,因為在改變背景色之前,這些條件都必須保持為真。
示例完整的XAML如下所示:
<Window x:Class="Styles.SimpleTriggers"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SimpleTriggers" Height="300" Width="300">
<Window.Resources>
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
</Style.Setters>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Control.IsFocused" Value="True"/>
<Condition Property="Control.IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Control.Foreground" Value="DarkRed" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
<!--<Style.Triggers>
<Trigger Property="Control.IsFocused" Value="True">
<Setter Property="Control.Foreground" Value="DarkRed" />
</Trigger>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.Foreground" Value="LightYellow" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Trigger>
<Trigger Property="Button.IsPressed" Value="True">
<Setter Property="Control.Foreground" Value="Red" />
</Trigger>
</Style.Triggers>-->
</Style>
</Window.Resources>
<StackPanel Margin="5">
<Button Padding="5" Margin="5"
Style="{StaticResource BigFontButton}"
>A Customized Button</Button>
<TextBlock Margin="5">Normal Content.</TextBlock>
<Button Padding="5" Margin="5"
>A Normal Button</Button>
<TextBlock Margin="5">More normal Content.</TextBlock>
<Button Padding="5" Margin="5"
Style="{StaticResource BigFontButton}"
>Another Customized Button</Button>
</StackPanel>
</Window>
SimpleTriggers
二、事件觸發器
普通觸發器等到屬性發生變化,而事件觸發器等待特定的事件被引發。可能會認為此時應使用設定器來改變元素,但情況并非如此。相反,事件觸發器要求使用者提供一系列修改空間的動作。這些動作通常被用于動畫。
下面的事件觸發器等待MouseEnter事件,然後動态改變按鈕的FontSize屬性進而形成動畫效果,在0.2秒得時間内将字型放大到22個機關:
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Style.Setters>
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="FontSize"
To="22" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
在XAML中,必須在故事般中定義每個動畫,故事闆為動畫提供了事件線。使用者可以在故事闆事件内部定義希望使用的一個或多個動畫對象。每個動畫對象執行本質上相同的任務:在一定時期内修改依賴項屬性。
為了恢複字型大小,樣式需要使用響應MouseLeave事件的事件觸發器,并在整整兩秒的時間内将字型尺寸縮小到原始尺寸。對于這種情況,不需要指明目标字型尺寸——如果沒有指明該目标,WPF假定希望使用第一次動畫之前按鈕原來的字型尺寸:
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Style.Setters>
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="FontSize" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
示例的完整XAML如下所示:
<Window x:Class="Styles.EventTriggers"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="EventTriggers" Height="300" Width="300">
<Window.Resources>
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Style.Setters>
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="FontSize"
To="22" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="FontSize" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="5">
<Button Padding="5" Margin="5"
Style="{StaticResource BigFontButton}"
>A Customized Button</Button>
<TextBlock Margin="5">Normal Content.</TextBlock>
<Button Padding="5" Margin="5"
>A Normal Button</Button>
<TextBlock Margin="5">More normal Content.</TextBlock>
<Button Padding="5" Margin="5"
Style="{StaticResource BigFontButton}"
>Another Customized Button</Button>
</StackPanel>
</Window>
EventTriggers
作者:Peter Luo
出處:https://www.cnblogs.com/Peter-Luo/
本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,并保留此段聲明,否則保留追究法律責任的權利。