WPF高級教程(十六)樣式

概念

樣式是可以應用於元素的一系列屬性值的集合。

樣式期望使用一份xaml代碼來設置一系列元素的細節,比如內外邊距,字體顏色等。

樣式類似於CSS但是要比CSS更加強大,強大之處在於:

  • 可以設置依賴項屬性,使其可以控制控件行爲
  • 支持觸發器
  • 可以使用模板重新定義控件的內置外觀

定義和設置樣式

定義樣式

<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>

設置樣式

<Button x:Name="btn" Style="{StaticResource BigFontButtonStyle}">Test Button</Button>

通過代碼設置樣式

btn.Style = (Style)window.FindResource("BigFontButtonStyle");

設置樣式

在上面最簡單的例子中我們看到了Setter的使用方法,這一節我們詳細看一下:

  • Setter只能使用在依賴項屬性上
  • Setter不是隻能設置字符串,也可以設置對象,需要用到下面的語法
    <Style x:Key="TestStyle">
        <Setter Property="Control.Background">
            <Setter.Value>
                <SolidColorBrush Color="Aquamarine"/>
            </Setter.Value>
        </Setter>
    </Style>
    
  • 如果上面的例子中這個畫刷要被多次使用,可以定義爲資源,下面的代碼體現了這樣的修改
    <SolidColorBrush x:Key="TestBrush" Color="Aquamarine"/>
    <Style x:Key="TestStyle">
        <Setter Property="Control.Background" Value="{StaticResource TestBrush}"/>
    </Style>
    

TargetType

我們在設置樣式的時候,我們發現在寫Property的時候,都是寫Control.Background,這是告訴樣式我們這個樣式應用於Control,但是我們寫多少個Setter就要寫多少次Control,爲了簡化寫法,我們推薦將對於一種類型控件的設置寫到一個樣式中併爲其指定TargetType,這樣可以簡化代碼

<Style TargetType="Button">
    <Setter Property="Background" Value="{StaticResource TestBrush}"/>
</Style>

如果在Style的屬性上指定了TargetType,就不需要在Property中再每一次都指定應用於什麼元素了。

樣式的繼承

樣式的繼承允許我們從一個樣式中繼承所有的設置,並且針對性的修改幾個屬性,需要使用BasedOn語法,我們看看其用法

<SolidColorBrush x:Key="TestBrush" Color="Aquamarine"/>
<Style x:Key="TestStyle">
    <Setter Property="Control.Background" Value="{StaticResource TestBrush}"/>
    <Setter Property="Control.FontWeight" Value="Bold"/>
</Style>
<Style x:Key="BaseStyle" BasedOn="{StaticResource TestStyle}">
    <Setter Property="Control.FontWeight" Value="Normal"/>
</Style>

如果按鈕使用了 BaseStyle 其底色是從TestStyle繼承而來的,但是其FontWeight是覆蓋之後的Normal

我們需要注意的是:只在有大量樣式相同,只有一點點不同需要改變的時候使用繼承語法,否則繼承語法帶來的樣式複雜性將使人得不償失。慎用。

應用範圍

之前我們都是使用x:Key來聲明一個樣式,如果不使用它,我們就需要注意樣式的應用範圍,我們記住下面兩種原則

  • 完全不指明的樣式不會被應用
    <!--不會被應用-->
    <Style>
        <Setter Property="Control.Background" Value="Red"/>
    </Style>
    
  • 只指明TargetType的樣式爲該控件在全局的默認樣式
    <!--會被應用到有效範圍內的所有按鈕-->
    <Style TargetType="Button">
        <Setter Property="Control.Background" Value="Red"/>
    </Style>
    

然而,我們需要十分謹慎的使用全局默認樣式,主要因爲在實際的開發中,我們經常會嵌套控件(使用模板),在對於某個控件的樣式設置可能會影響很多不需要影響的控件,而且,在開發過程中,突然出現的不知道來自於哪裏的默認樣式常常會讓我們十分抓狂,所以除非是明確的全局字體等,不要使用基於控件類型的全局的樣式。

樣式清除

給樣式賦值 {x:Null} 可以清除樣式

<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Control.Background" Value="Red"/>
    </Style>
</Window.Resources>
<StackPanel>
    <Button x:Name="btn" Style="{x:Null}">Test Button</Button>
</StackPanel>

上面例子中,按鈕使用 {x:Null} 清除了全局按鈕背景色帶來的影響。

Style類的屬性

不知不覺中,我們已經學了樣式的好幾個屬性,Setter 用於設置樣式,TargetType用於設置樣式應用的控件類型以及默認控件樣式,BasedOn用於繼承,而樣式不止這幾個屬性,還有下面幾個
在這裏插入圖片描述
由於觸發器比較重要所以我們下一節用一節的篇幅學習Style的另一個屬性,Trigger,觸發器。

我們先看Style的另外一些知識。

關聯事件處理程序

我們之前講了Setter,還有一種EventSetter,用於綁定事件。事先說明,這種用法使用的很少,不感興趣的可以直接跳過。

<Window.Resources>
    <Style TargetType="Button" x:Key="ClickBtnStyle">
        <EventSetter Event="Click" Handler="element_Click"/>
    </Style>
</Window.Resources>
<StackPanel>
    <Button x:Name="btn" Style="{StaticResource ClickBtnStyle}">Test Button</Button>
</StackPanel>

使用了ClickBtnStyle樣式的按鈕都會相應element_Click定義的點擊事件。這種寫法有一個限制就是必須寫在窗體或者控件中,無法寫在資源字典中(因爲它必須連接事件處理程序,所以必須指明x:Class,但是資源字典沒有這個屬性)

我們在實際的開發中應該儘量不使用這種技術,這裏僅做了解即可。

樣式與共享依賴屬性

我們在之前講依賴項屬性的時候提到過界面上Button和TextBlock雖然各自有各自的FontFamily屬性,但是本質上是同一個依賴項屬性的問題(因爲使用了共享的依賴項屬性),所以我們看下面的例子

<Style>
    <Setter Property="Button.FontFamily" Value="Times New Roman"/>
    <Setter Property="TextBlock.FontFamily" Value="Arial"/>
</Style>

在這個例子中我們期望把Button和TextBlock設置爲不同的字體,但是事實上,兩者的字體都被設置成了Arial,我們應當知道這個問題,在遇到問題的時候就可以節省很多解決問題的時間。

特別注意

  • 不僅僅是在樣式中可以使用觸發器,在FrameworkElement中也有Triggers集合,但是並不常用,因爲這裏面只能支持事件觸發器
  • 如果我們使用Background進行測試,我們經常會發現一些屬性的表現與我們設想的並不一致,這是因爲按鈕的行爲不止受樣式的影響,還受到模板的影響,兩者相結合我們才能真正的完全控制一個控件。再之後我們學習模板的時候我們還會慢慢理解這種關係
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章