[Windows 8|XAML] XAML元件屬性重複使用-資源(Resources)與樣式(Style)介紹

在學習開發XAML時,有時候畫面上某些元件可能會需要設定一樣的屬性(如:我有三個TextBlock都需要設定為顯示紅色字體,文字大小要32),但是一個一個設定不僅浪費時間,如果要做修改時,也要對每一個元件都重複做同樣的修改,耗時也費力。

而在XAML有一個資源的概念,可以把類似的這樣的元件屬性、樣式做一個事先的定義,然後再去對元件做指定套用。

在此篇主要會以在頁面資源(FrameworkElement.Resources)使用為主

前言

 


 

在學習開發XAML時,有時候畫面上某些元件可能會需要設定一樣的屬性(如:我有三個TextBlock都需要設定為顯示紅色字體,文字大小要32),但是一個一個設定不僅浪費時間,如果要做修改時,也要對每一個元件都重複做同樣的修改,耗時也費力。

而在XAML有一個資源的概念,可以把類似的這樣的元件屬性、樣式做一個事先的定義,然後再去對元件做指定套用。

在此篇主要會以在頁面資源(FrameworkElement.Resources)使用為主

 

資源(Resources)

 


 

如前言所述,有時候我們會遇到這樣的需求,這個時候資源的概念便派上用場了!

透過資源,我們可以事先透過定義好要套用到元件上的屬性,並且這總地億的資源可以重複使用!

資源是一種共享、反覆利用元素、屬性的機制。

可以用來定義的資源包含:

樣式(Style)與範本(Template)、筆刷(Brush)、故事版腳本(Storyboard)...等等,這些都各式是資源的一種

而以下我們會以介紹樣式(Style)為主,因為大多時候我們主要是針對XAML的元件(Button、Image、TextBlock、TextBox...)屬性做設定。

 

直接資源與應用程式資源

資源包含兩種類型:直接資源與頁面資源

 

直接資源:

FrameworkElement.Resources,或稱頁面資源,是針對單一頁面做資源配置,更詳細的說頁面資源只能被用在單一XAML頁面中的元件使用,在這邊,控制項的元件(Grid、StackPanel、Button、Rectangle等等)都包含Resources屬性(繼承自FrameworkElement),於是我們便可以在Resources標籤中定義我們想要使用的資源。

 

拿下圖來例子看的話,頁面資源分別就是XAML頁面A與頁面B,而頁面A中的資源定義只有頁面A看的到,同理頁面B的資源也只有頁面B的元件看的到,頁面A無法使用頁面B中所定義的資源。

 

 

但是一般會建議把資源的定義放在Page,因為這樣的好處是可以方便我們對所有的資源做一個管理。

假若今天我的XAML頁中的程式很大,這時在Grid中有資源,Button中有資源,並且我都需要做一些變動,這樣不就要來來回回的移動調整了嗎,所以建議把資源的定義放在Page,因為這樣的好處是可以方便我們對所有的資源做一個管理。

 

應用程式資源:

Application.Resources,可以使資源的定義被整個Application所看到,如果我在應用程式資源定義的話,以上面圖來看,的頁面A與頁面B,這兩個XAML頁面都可以使用我在應用程式資源事先定義Resources。

而在這邊我們先介紹直接資源,應用程式資源的部分會再另一篇做介紹。

 

那麼究竟使用資源是什麼樣的感覺呢?

 


 

以直接資源(頁面資源)為範例:

我們在Grid元件下拉入兩個TextBlock,然後我們透過Resources的定義來讓TextBlock套用同時改變!

這是原先不使用Resources的程式碼:

 


<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="32" Foreground="Red"  Margin="310,411,0,0"  Text="TextBlock"/>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="32" Foreground="Red"   Margin="677,411,0,0"  Text="TextBlock" />
        

 

再來是透過定義資源的方式:

 


<Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="32"/>
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
</Grid.Resources>
<TextBlock  Margin="310,411,0,0"  Text="TextBlock"/>
<TextBlock  Margin="677,411,0,0"  Text="TextBlock" />

結果顯示:

 

上面的範例中,原先我們對兩個TextBlock都做了一樣的屬性設定,但是在使用資源時,我們則是透過Style標籤的定義來讓後面的TextBlock一次套用。

而由於是使用頁面資源,我們需要讓被定義的Style資源被Resources標籤包覆住,因為在這個範例中,XAML非常少,且剛好兩個TextBlock是屬於Grid子標籤,所以便利用Grid.Resources作為我們定義用的區塊(但是再次提醒,一邊會建議放在Page中,Page.Resources,最後會提到)。

 

好的,在這邊我們進入此篇文章的另一個重點,樣式(Style)資源

 

Style(樣式)

樣式主要用來定義XAML元件中的屬性值,例如我的按鈕要什麼樣的文字大小,文字字型,文字顏色等等屬性。

樣式也是一種資源,所以需被放在有Resources屬性的標籤中。

 

以下讓我們再看一次前面的程式碼:


<Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="32"/>
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
</Grid.Resources>

 

Style:

是定義樣式用的標籤,其中TargetType這個屬性是用來指定你設定的元件,但是TargetType因為指定元件,所以全部在這個XAML頁面下的元件都會被套用。


<Style TargetType="TextBlock">

已上面這段程式碼來看,代表著我要對所有TextBlock的元件套用這個樣式

 

Setter:

設定Style中TargetType所指定的元件要變動的屬性,要改變的方式則是透過Property指定屬性,Value修改參數,以上面的例子來看:


<Setter Property="FontSize" Value="32"/>

修改字體就是TextBlock的FontSize大小為32,所以想要定義屬性即可以透過這個Setter標籤來完成

 

那麼回到先前所提到的,TargetType因為指定元件,所以全部在這個XAML頁面下的元件都會被套用,代表著我要對所有TextBlock的元件套用這個樣式。

如果今天我只要對特定的TextBlock修改要怎麼辦?

 

使用X:Key與StaticResource延伸標記修改特定元件的屬性

這次,我們來修改一下上面的範例,改成只要對左邊的TextBlock顯示紅色,右邊的TextBlock則顯示黃色文字。


<Grid.Resources>
            <Style TargetType="TextBlock" x:Key="RedColor">
                <Setter Property="FontSize" Value="32"/>
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
            <Style TargetType="TextBlock" x:Key="YellowColor">
                <Setter Property="FontSize" Value="32"/>
                <Setter Property="Foreground" Value="Yellow"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
 </Grid.Resources>
<TextBlock  Margin="310,411,0,0"  Text="TextBlock" Style="{StaticResource RedColor}"/>
<TextBlock  Margin="677,411,0,0"  Text="TextBlock" Style="{StaticResource YellowColor}"/>

在上面你會看到,我們增加了新的程式碼,在Style中一個叫做X:Key的關鍵字與TextBlock中加入Style="{StaticResource xxx}"

 

X:Key:

在Style中加入這段程式,代表我要對這個資源指定索引鍵,而這個索引鍵可以做為之後與個別元件做樣式的參考

 

Style="{StaticResource xxx}":

StaticResource 是一種延伸標記,透過這串語法,把先前所設定的X:Key的索引鍵做設定,可以取得事先定義好的Resources屬性

所以在上面的範例中我們分別定義了YellowColor的樣式與RedColor的樣式,並把Key值分別指定到兩個TextBlock的Style="{StaticResource xxx}中。

 

透過這樣一個對樣式

1.指定x:key與在元件中

2.在元件中設定Style,並做StaticResource 延伸標記參考x:key至我們事先定義好的Style資源

即可完成。

 

資源繼承

在上面的X:Key範例中,兩個TextBlock的差異只在顏色,而為了修改顏色,指定到不同的TextBlock,所以我們透過X:Key與StaticResource延伸標記來完成,但是你會看到有重複的Code,而這樣就違背了我們原先的美意,因此在這邊要介紹資源的繼承,來讓重複的XAML可以減少

 

使用BasedOn

BasedOn就如同物件導向中的繼承概念一樣,可以把婦類別的功能與成員屬性繼承下來:


<Grid.Resources>
            <Style TargetType="TextBlock" x:Key="Normal">
                <Setter Property="FontSize" Value="32"/>
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
            <Style TargetType="TextBlock" x:Key="YellowColor" BasedOn="{StaticResource Normal}">
                <Setter Property="Foreground" Value="Yellow"/>
            </Style>
            <Style TargetType="TextBlock" x:Key="RedColor" BasedOn="{StaticResource Normal}">
                <Setter Property="Foreground" Value="Red"/>
            </Style>
</Grid.Resources>
 <TextBlock  Margin="310,411,0,0"  Text="TextBlock" Style="{StaticResource RedColor}"/>
 <TextBlock  Margin="677,411,0,0"  Text="TextBlock" Style="{StaticResource YellowColor}"/>

X:Key="Normal"的樣式就是TextBlock共同的屬性設定,為了能夠辨別到父樣式而繼承下來,所以才會需要X:Key="Normal"

而下面的YellowColor與RedColor索引鍵樣式則是透過BasedOn與StaticResource延伸標記繼承下來,並加入新的屬性樣式,透過這樣的模式減少重複的屬性設定!

 

為了呼應我們前面提到的資源可重複使用性,這邊我而外再加入一個TextBlock,並對他套用YellowColor這個樣式,如下程式碼與結果,即便是有索引鍵的資源也是可以重複給別的元件使用!


 <Grid.Resources>
            <Style TargetType="TextBlock" x:Key="Normal">
                <Setter Property="FontSize" Value="32"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="VerticalAlignment" Value="Top"/>
            </Style>
            <Style TargetType="TextBlock" x:Key="YellowColor" BasedOn="{StaticResource Normal}">
                <Setter Property="Foreground" Value="Yellow"/>
            </Style>
            <Style TargetType="TextBlock" x:Key="RedColor" BasedOn="{StaticResource Normal}">
                <Setter Property="Foreground" Value="Red"/>
            </Style>
</Grid.Resources>
<TextBlock  Margin="310,411,0,0"  Text="TextBlock" Style="{StaticResource YellowColor}"/>
<TextBlock  Margin="677,411,0,0"  Text="TextBlock" Style="{StaticResource RedColor}"/>
 <TextBlock  Margin="983,411,0,0"  Text="TextBlock" Style="{StaticResource YellowColor}"/>

 

 

把頁面資源放在Page.Resources中

最後,在前面提到如果是單一頁面的話,基本上會建議把Resources放在Page,因為Page是XAML頁面的根,所以可以確保我整個頁面下的元件根可能被指定套上資源,另外一個好處則是,方便所以的樣式資源可以放在一起統一管理。

 

所以如下的XAML程式碼,便是移動到Page的Resources下,整個Windows 8 App的XAML檔最外層是Page,所以我們在這邊加入了Page.Resources的標籤,並把Style樣式定義包覆在其中。


<Page.Resources>
        <Style TargetType="TextBlock" x:Key="Normal">
            <Setter Property="FontSize" Value="32"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="VerticalAlignment" Value="Top"/>
        </Style>
        <Style TargetType="TextBlock" x:Key="YellowColor" BasedOn="{StaticResource Normal}">
            <Setter Property="Foreground" Value="Yellow"/>
        </Style>
        <Style TargetType="TextBlock" x:Key="RedColor" BasedOn="{StaticResource Normal}">
            <Setter Property="Foreground" Value="Red"/>
        </Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" HorizontalAlignment="Left" Width="1366">
        <TextBlock  Margin="380,397,0,0"  Text="TextBlock" Style="{StaticResource YellowColor}"/>
        <TextBlock  Margin="614,397,0,0"  Text="TextBlock" Style="{StaticResource RedColor}"/>
        <TextBlock  Margin="832,397,0,0"  Text="TextBlock" Style="{StaticResource YellowColor}"/>
</Grid>

 

結論

 


 

善用資源可以讓你的XAML頁面整齊,捨去重複的程式碼,同時若你要重修調整或修改維護你的XAML程式時,也可以加快你的修改速度(因為你不再需要一個一個去修改)。

 

參考資料:

XAML資源

 


 

文章中的敘述如有觀念不正確錯誤的部分,歡迎告知指正 謝謝 =)

另外要轉載請附上出處 感謝