[Windows 8|XAML] 應用程式資源(Application Resources)使用與資源字典(ResourceDictionary)的介紹

前言


前篇中,向各位介紹了如何把XAML元件的屬性做一個重複使用的方式,好處是:

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

而在前篇中我們提到了資源有分兩種:

直接資源(頁面資源)與應用程式資源兩種,而在此篇中,除了再次提一下頁面資源,再來主要會介紹如何使用應用程式資源(Application Resources),與一個新的標籤ResourceDictionary。

直接資源與應用程式資源


直接資源:

FrameworkElement.Resources,或稱頁面資源,是針對單一頁面做資源配置,更詳細的說頁面資源只能被用在單一XAML頁面中的元件使用,在這邊,控制項的元件(Grid、StackPanel等等)都包含Resources屬性(繼承自FrameworkElement),於是我們便可以在Resources標籤中定義我們想要使用的資源;但是一般會建議把資源的定義放在Page,因為Page是XAML頁面的根,所以可以確保我整個頁面下的元件根可能被指定套上資源。

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

應用程式資源:

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

使用應用程式資源(Application Resources)


當我們開啟Windows Store App專案後,在專案中你會看到一個App.xaml檔案

點開後你會看到下面這樣的程式碼:

<Application
    x:Class="ResourcesIntro.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ResourcesIntro">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    定義平台外觀及操作之通用層面的樣式
                    Visual Studio 專案及項目範本的必要項
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>
    </Application.Resources>
</Application>

這個App.xaml檔是管理整個你的應用程式相關的資源一些設定,而這邊你也會看到一個關鍵的標籤-Application Resources,所以如果今天我希望在許多個XAML頁面都可以使用到同樣的資源,那麼就可以在這邊去做一個樣式定義。

但是在這邊,你會看到一個新的標籤-ResourceDictionary,這個標籤容我需要好好介紹一下,因為他很重要。

ResourceDictionary(資源字典)


基本上我們在XAML定義資源的時候,是有透過資源字典這個標籤來做管理,資源字典是用來定義資源並管理,透過StaticResources延伸標記參考到的字典物件。

在前篇,我們使用頁面資源(FrameworkElement.Resources)定義樣式時,其實樣式是屬於ResourceDictionary的型態,所以我們才可以對定義好的樣式做StaticResources延伸標記參考(樣式是一種資源,資源是ResourceDictionary類別)

另外,因為ResourceDictionary繼承了IDictionary的介面,所以基本上放入的資源一定要有Key索引鍵值,但是在前篇的第一個範例中,我們對兩個TextBlock做文字顏色的紅色設定時,並未使用到x:key,但他卻沒有出錯!為何?

原因在於,當下我們有指定Style的TargetType為TextBlock,基本上若有設定TargetType,ResourceDictionary的Key值就會套用到TargetType我們所指定的類型,所以即便沒有指定x:key的值也可以(注意!只有Style與Template樣本是這樣的情況)

而在應用程式資源中(Application.Resources),因為預設便加入了ResourceDictionary標籤,所以我們只要把需要加入的樣式放置ResourceDictionary標籤結構內即可,並且透過這個ResourceDictionary使資源能夠在整個應用程式層級的範圍中被保留。

所以這也是ResourceDictionary很重要。

再來,讓我們回到如何使用應用程式資源。

原先XAML頁面資源範例

我們加入了三個TextBlock並透過頁面資源的方式把顏色設定為黃色、紅色、黃色。

 <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}"/>

使用Application.Rexoures應用程式資源範例

我把原先的XAML頁面中的樣式資源拿到App.xaml檔案的Application.Resources中,並且我在這邊加入了一個新的空白頁XAML到我的專案中(BlankPage.xaml),同樣指定並且加入三個TextBlock

1.應用程式資源加入樣式

<Application
    x:Class="ResourcesIntro.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ResourcesIntro">

    <Application.Resources>
        <ResourceDictionary>
            <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>
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    定義平台外觀及操作之通用層面的樣式
                    Visual Studio 專案及項目範本的必要項
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

2.加入BlankPage與TextBlock

<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}"/>

結果:

兩個XAML檔都使用StaticResources延伸標記參考樣式資源,並且兩個頁面都套用到了樣式!

結論


如果說你有需要再多的XAML頁面中都使用到相同的樣式資源,那麼便可以建議使用應用程式資源來做管理

接下來,還會再向各位介紹另一篇,製作自己的的資源字典檔。

參考資料

ResourceDictionary與XAML資源參考

ResourceDictionary Class

FrameworkElement.Reources Property

Application.Resources

For more complete information about compiler optimizations, see our Optimization Notice.