【WPF學習】第三十七章 觸發器


  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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM