WPF中有個主題,就是以聲明方式擴展代碼的功能。當使用樣式、資源或數據綁定時,將發現即便不使用代碼,也能完成很多工做。ide
觸發器是另外一個實現這種功能的例子。使用觸發器,可自動完成簡單的樣式改變,而這一般須要使用樣板事件處理邏輯。例如,當屬性發生變化時能夠進行響應,並自動調整樣式。字體
觸發器經過Style.Triggers集合連接到樣式。每一個樣式均可以有任意多個觸發器,並且每一個觸發器都是System.Windows.TriggerBase的派生類的實例。下表列出了WPF中的選項。動畫
表 繼承自TriggerBase的類spa
經過使用FrameworkElement.Triggers集合,可直接爲元素應用觸發器,而不須要建立樣式。但這存在一個至關大的缺陷。這個Triggers集合只支持事件觸發器(並不是技術上的緣由形成了該限制,只是由於WPF團隊沒時間實現該特性,未來的版本中可能包含該特性)。code
1、簡單觸發器orm
可爲任何依賴項屬性關聯簡單觸發器。例如,可經過響應Control類的IsFocused、IsMouseOver以及IsPressed屬性的變化,建立鼠標懸停效果和焦點效果。xml
每一個簡單觸發器都制定了正在監視的屬性,以及正在等待的屬性值。當該屬性值出現時,將應用存儲在Trigger.Setters集合中的設置器(但不能使用更復雜的觸發器邏輯。例如,比較某個值以查看其是否處於某個範圍,或執行某種計算等。對於這些狀況,最好使用事件處理程序)。對象
下面的觸發器等待按鈕得到鍵盤焦點,當獲取焦點時會將前景色設置爲深紅色:blog
<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>
2、事件觸發器
普通觸發器等到屬性發生變化,而事件觸發器等待特定的事件被引起。可能會認爲此時應使用設置器來改變元素,但狀況並不是如此。相反,事件觸發器要求用戶提供一系列修改空間的動做。這些動做一般被用於動畫。
下面的事件觸發器等待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>