樣式基礎
樣式(Style)是組織和重用格式化選項的重要工具。不是使用重復的標記填充XAML,以便設置外邊距、內邊距、顏色以及字體等細節,而是創建一系列封裝所有這些細節的樣式,然后再需要之處通過屬性來應用樣式。
樣式是可應用於元素的屬性值集合。使用資源的最常見原因之一就是保存樣式。
使按鈕具有統一格式的實現方式一:資源
<Window.Resources> <FontFamily x:Key="ButtonFontFamily">Times New Roman</FontFamily> <sys:Double x:Key="ButtonFontSize">18</sys:Double> <FontWeight x:Key="ButtonFontWeight">Bold</FontWeight> </Window.Resources> <Grid Name="gird1" ShowGridLines="True"> <Button FontFamily="{StaticResource ButtonFontFamily}" FontSize="{StaticResource ButtonFontSize}" FontWeight="{StaticResource ButtonFontWeight}"> </Button> </Grid>
這個示例可以正常工作,它將字體細節(所謂的magic number)移出的標記。但也存在兩個問題。
-
除了資源的名稱相似之外,沒有明確指定三個資源是相關的。這使維護應用程序變得復雜。
-
需要使用資源的標記非常繁瑣。還沒有原來不使用資源時簡明。
樣式為解決這個問題提供了非常好的解決方案。可獨立的用戶封裝所有希望設置的屬性的樣式。
<Window.Resources> <Style x:Key="BigFontButtonStyle"> <Setter Property="Control.FontFamily" Value="Times New Roman"/> <Setter Property="Control.FontSize" Value="18"/> <Setter Property="Control.FontWeight" Value="Bold"/> </Style> </Window.Resources> <Grid Name="gird1" ShowGridLines="True"> <Button Style="{StaticResource BigFontButtonStyle}"> </Button> </Grid>
通過樣式系統不僅可以創建多組明顯相關的屬性設置,而且使得應用程序這些設置更加容易,從而精簡了標記。
設置屬性
每個Style對象都封裝了一個Setter對象的集合。每個Setter對象設置元素的單個屬性。在某些情況下不能使用簡單的特性字符設置屬性值。可使用嵌套的元素代替如:
<Setter Property="Control.Background"> <Setter.Value> <ImageBrush TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="" Opacity="0.3"></ImageBrush> </Setter.Value> </Setter>
創建只應用按鈕的樣式
<Style x:Key="BigFontButtonStyle" TargetType="Button"> <Setter Property="FontFamily" Value="Times New Roman"/> <Setter Property="FontSize" Value="18"/> <Setter Property="FontWeight" Value="Bold"/> </Style>
關聯事件處理程序
實現大量元素鼠標懸停效果。
<Window.Resources> <Style x:Key="MouseOverHighlightStyle"> <EventSetter Event="TextBlock.MouseEnter" Handler="element_MouseEnter"></EventSetter> <EventSetter Event="TextBlock.MouseLeave" Handler="element_MouseLeave"></EventSetter> </Style> </Window.Resources> <Grid Name="gird1" ShowGridLines="True"> <TextBlock Style="{StaticResource MouseOverHighlightStyle}"></TextBlock> </Grid>
多層樣式
每個WPF元素一次只能使用一個樣式對象,這像是一種限制,但由於屬性值的繼承和樣式繼承特性,這種限制實際是不存在的。例如,希望為一組控件使用相同的字體,又不想為每個控件應用相同的樣式。對於這種情況,可將他們放置到面板中,並設置容器的樣式。只要設置的屬性具有屬性值繼承特性,這些值就會傳遞到子元素。使用這種模型的屬性包括
IsEnabled、IsVisible、Foreground以及所有字體屬性。
另外一些情況,可能希望在另一個樣式的基礎上建立樣式,可用BasedOn特性。
<Window.Resources> <Style x:Key="BigFontButtonStyle"> <Setter Property="Control.FontFamily" Value="Times New Roman"/> <Setter Property="Control.FontSize" Value="18"/> <Setter Property="Control.FontWeight" Value="Bold"/> </Style> <Style x:Key="NewBigButtonBigFontStyle" BasedOn="{StaticResource BigFontButtonStyle}"> <Setter Property="Control.Foreground" Value="Red"/> <Setter Property="Control.Background" Value="DarkBlue"/> </Style> </Window.Resources> <Grid Name="gird1" ShowGridLines="True"> <TextBlock Style="{StaticResource NewBigButtonBigFontStyle}">test</TextBlock> </Grid>
通過類型自動應用樣式
上面都是具有名稱的樣式,還有一種為特定類型元素自動應用的樣式。
<Window.Resources> <Style TargetType="Button"> <Setter Property="Control.FontFamily" Value="Times New Roman"/> <Setter Property="Control.FontSize" Value="18"/> <Setter Property="Control.FontWeight" Value="Bold"/> </Style> </Window.Resources> <Grid Name="gird1" ShowGridLines="True"> <Button>one</Button> <Button Style="{x:Null}">two</Button> <Button>three</Button> </Grid>
上面的例子中第二個按鈕顯示替換了樣式,將style設置為null,有效的刪除了樣式。
觸發器
使用觸發器可自動完成簡單的樣式的改變,不需要使用代碼,也可以完成不少工作。
觸發器通過Style.Trigger集合鏈接到樣式。每個樣式可以有任意多個觸發器。每個觸發器都是System.Windows.TriggerBase的實例。
TriggerBase的子類
| 名稱 | 說明 |
| Trigger | 這是一種最簡單的觸發器。可以監測依賴項屬性的變化,然后設置器改變樣式。 |
| MultiTrigger | 與Trigger類似,但這種觸發器聯合了多個條件。只有滿足了所有這些條件,才會啟動觸發器。 |
| DataTrigger | 這種觸發器使用數據綁定,與Trigger類似,只不過監視的是任意綁定數據的變化。 |
| MultiDataTrigger | 聯合多個數據觸發器。 |
| EventTrigger | 這是最復雜的觸發器。當事件發生時,這種觸發器應用動畫。 |
簡單觸發器
可為任何依賴項屬性關聯簡單觸發器。例如,可通過相應Control類的IsFocused、IsMouseOver以及IsPressed屬性的變化,創建鼠標懸停效果和焦點效果。
每個觸發器都制定了正在監視的屬性以及正在等待的屬性值。當屬性值出現時,將應用Trigger.Setters集合里的設置器。
<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> <Trigger Property="Control.IsFocused" Value="True"> <Setter Property="Control.Foreground" Value="DarkRed"/> </Trigger> </Style.Triggers> </Style> </Window.Resources>
觸發器的優點是不需要為翻轉他們而編寫任何代碼。
如果希望幾個條件都滿足時才激活觸發器,可使用MultiTrigger
<Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Property="Control.IsFocused" Value="true"/> <Condition Property="Control.IsMouseOver" Value="true"/> </MultiDataTrigger.Conditions> <MultiDataTrigger.Setters> <Setter Property="Control.Foreground" Value="DarkRed"/> </MultiDataTrigger.Setters> </MultiDataTrigger> </Style.Triggers>
事件觸發器
普通觸發器等待屬性發生變化,而事件觸發器等待特定事件被引發。事件觸發器要求用戶提供一系列修改控件的動作。這些動作常用於動畫。
如監聽MouseEnter事件,然后動態改變按鈕的FontSize屬性從而形成動畫效果,在0.2秒的時間內容字體放大到22個單位。
<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:3" Storyboard.TargetProperty="FontSize" To="50"/> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="Mouse.MouseLeave"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="0:0:3" Storyboard.TargetProperty="FontSize"/> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Style.Triggers> </Style> </Window.Resources> <Grid Name="gird1" ShowGridLines="True"> <Button HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource BigFontButton}">onesfsfsfsfsdfsdf</Button> </Grid>
與屬性觸發器不同如果希望元素返回原始狀態,需要反轉事件觸發器。如上面例子,需要編寫MouseLeav事件的觸發器。不需要指明字體的大小,默認會恢復成第一次動畫之前的字體大小。
