樣式簡介:樣式(style)是組織和重用格式化選項的重要工具,不是使用重復的標記填充XAML,以便設置外邊距、內邊距、顏色以及字體等細節。而是創建一系列封裝所有這些細節的樣式,然后在需要之處通過屬性來設置樣式。名稱空間是System.Windows。
1、樣式。
為了理解適合使用樣式的集合,分析一個簡單的示例,設想需要標准化在窗口中使用的字體,最簡單的方式是設置包含窗口的字體屬性,這些屬性都是在Control類中定義的,包括FontFamily、FontSize、FontWeight,得益於這些屬性值的繼承,當在窗口級別設置這些屬性時,窗口中的所有元素都會使用相同的屬性值。
定義一個普通的資源:
<Window.Resources>
<!-- 定義一個FontFamily資源對象 -->
<FontFamily x:Key="TextBlockFontFamily">楷體</FontFamily>
<!-- 定義一個FontWeight資源對象 -->
<FontWeight x:Key="TextBlockFontWeight">Bold</FontWeight>
</Window.Resources>
定義一個TextBlock,引用資源:
<TextBlock FontFamily="{StaticResource TextBlockFontFamily}" FontSize="30" FontWeight="{StaticResource TextBlockFontWeight}">今天天氣好晴朗!!!</TextBlock>
在使用資源設置屬性時,正確地匹配類型是非常重要的,這個時候用到的是類型轉換器,如果為元素設置FontFamily對象,FontFamilyConverter轉換器會創建所需要的FontFamily對象。
這種寫法的弊端:
除了資源名稱相似外,並沒有明確指明這三個資源是相關的,這使維護變得非常復雜。
需要使用資源的標記非常繁瑣。
這個時候樣式就可以很好地解決這種解決方案(定義樣式):
<Window.Resources>
<Style x:Key="TextBlockStyle">
<Setter Property="Control.FontFamily" Value="楷體"></Setter>
<Setter Property="Control.FontSize" Value="20"></Setter>
<Setter Property="Control.FontWeight" Value="Bold"></Setter>
</Style>
</Window.Resources>
名叫TextBlockStyle的樣式對象包含了一個設置器集合,該集合包含了三個Setter對象,每一個Setter對象用於一個希望設置的屬性,每個setter屬性對象由兩部分信息組成,分別是希望進行設置的屬性名稱和希望為該屬性應用的值。與所有資源一樣,樣式和對象都有一個鍵名。
在xaml中引用:
<TextBlock Name="TextBlock1" Style="{StaticResource TextBlockStyle}">Hello,World!!!</TextBlock>
用代碼設置:
TextBlock1.Style = (Style)FindResource("TextBlockStyle");
2、Style類的常用屬性。
Style類的常用屬性 |
|
屬性名 |
說明 |
Setters |
設置屬性值以及自動關聯事件處理程序的Setter對象或者EventSetter對象的集合。 |
Triggers |
繼承自TriggerBase類,並能自動改樣式設置對象的集合,例如當某個屬性改變時,或者是發生某個事件時,可以修改樣式。 |
Resources |
希望用於樣式的資源集合。 |
BaseOn |
通過該屬性可用於創建繼承自其他樣式設置的更具體形式。 |
TargetType |
該屬性標識應用央視的元素的類型,通過該屬性可創建只影響特定類型元素的設置器,還可以創建能夠為恰當的元素類型自動其作用的設置器。 |
3、創建樣式對象(嵌套元素)。
每一個Style對象都封裝了一個Setter對象的集合,每個Setter對象設置元素的單個屬性,只能設置依賴項屬性,不能修改其他屬性。
<TextBlock Text="孤獨和迷茫時成長的必經之路!">
<TextBlock.Style>
<Style>
<Setter Property="Control.FontWeight" Value="Bold"></Setter>
<Setter Property="Control.FontSize" Value="20"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
4、設置元素類型(TargetType)並自動應用樣式。
通過TargetType指定類類型。如果去掉x:key特性,那么就會自動應用到元素類型了。將元素的Style屬性設置為x:Null 可取消自動應用樣式。
<!--如果不寫x:key特性,就會自動為類元素設置style樣式了,不用再通過元素的style屬性設置樣式了。-->
<Window.Resources>
<Style TargetType="Button" >
<Setter Property="Control.FontFamily" Value="楷體"></Setter>
<Setter Property="Control.FontWeight" Value="Bold"></Setter>
<Setter Property="Control.FontSize" Value="30"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Height="50">孤獨和時成長的必經之路!</Button>
<!--通過x:Null取消樣式設置。-->
<Button Height="50" Style="{x:Null}">孤獨和時成長的必經之路!</Button>
</StackPanel>
6、多層樣式(通過BaseOn繼承)。
盡管可在許多不同層次定義任意數量的樣式,但每個WPF元素一次只能使用一個樣式對象。這好像是一種限制,但由於屬性值繼承和樣式繼承特性,可通過BaseOn屬性繼承樣式即可。 如果兩次設置了同一個屬性,那么最后一次設置的樣式會覆蓋之前設置的樣式。
<Window.Resources>
<!--設置一個字體樣式-->
<Style x:Key="SetButtonFontSize">
<Setter Property="Control.FontSize" Value="30"></Setter>
</Style>
<!--設置一個字體類型樣式,通過BaseOn屬性繼承字體大小樣式-->
<Style x:Key="SetButtonFontFamily" BasedOn="{StaticResource SetButtonFontSize}">
<Setter Property="Control.FontFamily" Value="楷體"></Setter>
</Style>
<!--設置一個字體粗細,通過BaseOn屬性繼承字體類型,這樣這個樣式就擁有了字體類型的字體大小的樣式了-->
<Style x:Key="SetButtonBold" BasedOn="{StaticResource SetButtonFontFamily}">
<Setter Property="Control.FontWeight" Value="Bold"></Setter>
<!--如果再設置字體大小,那么就以最后一次設置為准。-->
<Setter Property="Control.FontSize" Value="40"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Style="{StaticResource SetButtonBold}">Hello,World!!!</Button>
</StackPanel>
7、觸發器(Trigger)。
WPF有個主題,就是以聲明的方式擴展代碼的功能,當使用樣式、資源或者數據綁定時,將發現即使不適用代碼,也能完成不少工作,這個時候就要使用觸發器了,當屬性發生變化時,可以進行響應,並自動調整樣式。每個樣式可以有任意多個觸發器,而且每個觸發器都是System.Windows.TriggerBase的派生類的實例。
簡單理解就是:在樣式中設置觸發器,在觸發器中設置屬性名稱和屬性值。
繼承自TriggerBase的類 |
|
Trigger |
這是一種簡單的觸發器,可以監測依賴項屬性的變化,然后使用設置器改變樣式 |
MultiTrigger |
與Trigger類似,但這種觸發器聯合了多個條件,只有滿足了所有這些條件,才會啟動出觸發器 |
DataTrigger |
數據綁定觸發器 |
MultiDataTrigger |
聯合多個數據觸發器 |
EventTrigger |
這是復雜的觸發器,當事件發生時,這種觸發器應用動畫 |
7.1、簡單觸發器。
可以為任何依賴項屬性關聯簡單觸發器,每個簡單的觸發器都指定了正在監視的屬性,以及正在等待的屬性值,當屬性值出現時,將應用存儲在Trigger.Setters集合中的設置器(不能使用復雜的觸發器邏輯)。
<Window.Resources>
<Style x:Key="BigFontButton">
<Style.Setters>
<Setter Property="Control.FontSize" Value="30"></Setter>
<Setter Property="Control.FontFamily" Value="楷體"></Setter>
</Style.Setters>
<!--在樣式中設置觸發器-->
<Style.Triggers>
<!--如果元素獲取了焦點。-->
<Trigger Property="Control.IsFocused" Value="true">
<!--設置其中的元素屬性。設置前景色為紫色。-->
<Setter Property="Control.Foreground" Value="Pink"></Setter>
</Trigger>
</Style.Triggers>
</Style>
<!--設置一個簡單的觸發器,在觸發器中改變元素的背景色。-->
<Style x:Key="SetButton">
<Style.Triggers>
<Trigger Property="Control.IsFocused" Value="true">
<Setter Property="Control.Background" Value="Yellow"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<!--設置第一個樣式-->
<Button Style="{StaticResource BigFontButton}">Hello,World!!!</Button>
<!--設置第二個樣式-->
<Button Style="{StaticResource SetButton}" Height="50" FontSize="30">Hello,World!!!</Button>
</StackPanel>
7.2、為元素設置樣式(嵌套形式)。
<Button Height="50" FontSize="30" Content="今天天氣好晴朗!!!">
<Button.Style>
<Style>
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="true">
<!--可將S屬性樣式寫在Trigger.Setters中(方式一)-->
<!--<Trigger.Setters> <Setter Property="Control.Foreground" Value="Red"></Setter> </Trigger.Setters>-->
<!--(方式二)-->
<!--也可以直接寫在Triggr中,視情況而定,如果觸發器滿足多個條件時,要使用第一種方式設置屬性值。-->
<Setter Property="Control.Foreground" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
7.3、MultiTrigger觸發器(滿足多條件的觸發器)。
如果希望創建只有當幾個條件都為真時才激活的觸發器,可使用MultiTrigger,這種觸發器提供了一個Conditions(條件)集合,可通過該集合定義一系列屬性值的集合。
<Window.Resources>
<Style x:Key="SetButton">
<!--觸發器-->
<Style.Triggers>
<!--使用多條件觸發器-->
<MultiTrigger>
<!--通過Conditions屬性設置多個條件(一個是獲取焦點和鼠標移動到元素上。)。-->
<MultiTrigger.Conditions>
<Condition Property="Control.IsFocused" Value="true"></Condition>
<Condition Property="Control.IsMouseOver" Value="true"></Condition>
</MultiTrigger.Conditions>
<!--設置多個屬性值-->
<MultiTrigger.Setters>
<Setter Property="Control.FontSize" Value="30"></Setter>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<!--設置樣式。-->
<Button Style="{StaticResource SetButton}">Hello,World!!!</Button>
</StackPanel>
7.4、事件觸發器。
普通觸發器是等待屬性發生變化,而事件觸發器是等待特定的事件被引發。事件觸發器要求用戶提供一系列修改控件的動作,這些動作通常被應用為動畫。
<Window.Resources>
<Style x:Key="SetButtonMouseOver">
<!--設置觸發器-->
<Style.Triggers>
<!--設置觸發器的路由事件-->
<EventTrigger RoutedEvent="Control.MouseEnter">
<!--設置一個動畫,改變元素的字體的大小-->
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0:2" Storyboard.TargetProperty="FontSize" To="30"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<!--設置樣式-->
<Button Style="{StaticResource SetButtonMouseOver}">Hello,World!!!</Button>
</StackPanel>
End!