建立和使用整個應用程式的資源

已完成

在 XAML 頁面上定義資源與樣式,是減少重複程式碼的好方法。 不過,有一個問題。 那些資源與樣式僅供在該特定的 XAML 頁面上使用。 當您有多個頁面時,頁面層級資源字典並不足以讓您在整個應用程式避免重複的程式碼。 在此單元,您會學習如何在應用程式的所有頁面中共用資源與樣式。

哪裡可以找到資源字典

[ VisualElement ] 類別定義 [ 資源 ] 屬性。 控制項、頁面和版面配置是從 [ VisualElement ] 繼承而來,因此它們都具有 [ 資源 ] 屬性以保留資源字典。

[ 應用程式 ] 類別也會定義 [ 資源 ] 屬性。 [ 應用程式 ] 不會繼承至 [ VisualElement ] ,因此屬性定義為該類別的一部分。

下圖顯示一般應用程式的結構。 每個顯示的元素都有一個可以保留資源字典的 [ 資源 ] 屬性。

注意

這張圖表以較簡易的方式描繪在應用程式裡的項目是如何被組織的。 在這張圖表中,[檢視] 這個字詞指的是不會作為任何子項目容器的單一控制項,例如 [按鈕] 或 [標籤]。 此外,[ 版面配置 ] 一詞也意味著負責組織其子項目版面配置的容器。 版面可以巢狀方式配置。 例如 [ 格線 ] 控制項可保存於 [ StackLayout ] 控制項中。

A diagram of the high-level structure of a typical .NET MAUI application.

如何定義應用程式層級的資源與樣式

與您 [ 應用程式 ] 類別相關聯的 XAML 檔案中,應用程式層級的資源及樣式由您定義。 下列程式碼顯示如何在應用程式資源字典中宣告 [ 色彩 ] 資源。

<Application.Resources>
    <Color x:Key="MyTextColor">Blue</Color>
</Application.Resources>

.NET MAUI 如何定位資源或樣式

假設您將資源套用至您其中一個控制項,如下列程式碼所示。

<Label TextColor="{StaticResource MyTextColor}" ... />

.NET MAUI 必須定位該資源的定義以便套用該值。 我們知道單一應用程式可以有許多的字典。 .NET MAUI 會搜尋哪些字典,而其搜尋順序又為何? 若欲回答這些問題,將頁面上的 [ VisualElement ] 執行個體想像成樹狀結構會有幫助。 應用程式位於根部,而頁面、版面配置,以及檢視則分散於其下。 這種結構通常稱為「視覺化樹狀結構」。 樹狀目錄中的每個元素都可以有自己的字典,其中可包含資源。 .NET MAUI 中的樣式搜尋演算法會在視覺樹狀結構向上延伸:

  1. 使用 [ VisualElement ] 執行個體中套用資源的字典開始搜尋。 在上一個範例中,搜尋會以 [ 標籤 ] 類型開頭。 若它沒有字典,或是有字典但該資源不存在,搜尋就會繼續進行下去。

  2. 請移至父代(控制項)並再次搜尋。 通常,接下來要搜尋的位置是版面配置。

  3. 檢查版面配置的父代。 通常要搜尋的下一個位置是頁面,但若版面配置巢狀嵌入另一個版面配置 (例如嵌入 [ StackLayout ] 的 [ 格線 ]),則搜尋會上移至樹狀結構的父代版面配置。

  4. 在字典中查看 [ 應用程式 ] 類別。

搜尋會傳回具有相符 x:Key 值的第一個項目。 下圖摘要說明資源查閱順序。

A diagram showing how .NET searches for resources. It starts at the view, then layouts, then pages, then to the application.

在實務上,大部分開發人員都會忽略檢視和版面配置面板中的 [ 資源 ] 屬性。 他們會針對在單一頁面上使用的項目使用頁面層級字典。 針對要在多個頁面上共用的資源與樣式,則會在應用程式層級定義。 查閱程序接下來只需要檢查兩個字典:目前執行個體中的字典和應用程式中的字典。

注意

若找不到具有指定金鑰的資源,應用程式會使用預設值進行樣式輸入。

重複索引鍵

每個 [ ResourceDictionary ] 執行個體都是獨立的,這表示可以在多個字典中使用相同的 x:Key 值。 在搜尋路徑上若讓多個字典具有相同的 x:Key 識別碼並不會造成錯誤。 使用的是與路徑上第一個相符 x:Key 值相關聯的資源。

例如,假設您在 [ 應用程式 ] 類別中有下列資源:

<Application.Resources>
    <x:String x:Key="msg">Two</x:String>
</Application.Resources>

接著,您在 ContentPage 中定義下列資源,並將其套用至相同頁面上的 [ 標籤 ]:

<ContentPage.Resources>
    <x:String x:Key="msg">One</x:String>
</ContentPage.Resources>
...
<Label Text="{StaticResource msg}">

由於使用了第一個相符的 x:Key 值,因此 Text 屬性會設定為 One