資源字典
.NET 多平台應用程式 UI (.NET MAUI) ResourceDictionary 是 .NET MAUI 應用程式所使用的資源存放庫。 儲存在 ResourceDictionary 中的一般資源包括樣式、控件範本、數據範本、轉換器和色彩。
儲存在 中的 ResourceDictionary XAML 資源可以使用 或 DynamicResource
標記延伸來參考並套用至專案StaticResource
。 在 C# 中,您也可以在 中 ResourceDictionary 定義資源,然後使用字串型索引器參考並套用至元素。
提示
在 Visual Studio 中,程式代碼後置檔案所支援的 XAML 型 ResourceDictionary 檔案可以透過 .NET MAUI ResourceDictionary (XAML) 專案範本新增至您的專案。
建立資源
每個 VisualElement 衍生物件都有屬性 Resources
,也就是 ResourceDictionary 可以包含資源的 。 同樣地, Application
衍生物件具有 Resources
屬性,也就是 ResourceDictionary 可以包含資源的 。
.NET MAUI 應用程式只能包含衍生自 Application
的單一類別,但通常會使用衍生自 VisualElement的許多類別,包括頁面、版面配置和檢視。 這些物件中的任何一個都可以將其 Resources
屬性設定為 ResourceDictionary 包含資源的 。 選擇要將資源用於何處的特定 ResourceDictionary 影響:
- ResourceDictionary中附加至檢視的資源,例如 Button 或 Label,只能套用至該特定物件。
- ResourceDictionary附加至配置的資源,例如 StackLayout 或 Grid,可以套用至配置和該版面配置的所有子系。
- ResourceDictionary在頁面層級定義的資源可以套用至頁面及其所有子系。
- ResourceDictionary在應用層級定義的 資源可以在整個應用程式中套用。
除了隱含樣式之外,資源字典中的每個資源都必須具有以 x:Key
屬性定義的唯一字串索引鍵。
下列 XAML 會顯示在 App.xaml 檔案應用程式層級ResourceDictionary中定義的資源:
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.App">
<Application.Resources>
<Thickness x:Key="PageMargin">20</Thickness>
<!-- Colors -->
<Color x:Key="AppBackgroundColor">AliceBlue</Color>
<Color x:Key="NavigationBarColor">#1976D2</Color>
<Color x:Key="NavigationBarTextColor">White</Color>
<Color x:Key="NormalTextColor">Black</Color>
<!-- Images -->
<x:String x:Key="BackgroundImage">background</x:String>
<x:String x:Key="MenuIcon">menu.png</x:String>
<x:String x:Key="SearchIcon">search.png</x:String>
<!-- Implicit styles -->
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor"
Value="{StaticResource NavigationBarColor}" />
<Setter Property="BarTextColor"
Value="{StaticResource NavigationBarTextColor}" />
</Style>
<Style TargetType="ContentPage"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
</Application.Resources>
</Application>
在此範例中,資源字典會定義資源、多個Color資源,以及兩個Thickness
隱含Style資源。
重要
直接在屬性項目標記之間 Resources
插入資源會自動建立 ResourceDictionary 物件。 不過,在選擇性 ResourceDictionary 標籤之間放置所有資源也是有效的。
取用資源
每個資源都有使用 x:Key
屬性指定的索引鍵,這會成為 中的 ResourceDictionary字典索引鍵。 索引鍵是用來從 ResourceDictionary 參考具有 StaticResource
或 DynamicResource
XAML 標記延伸的資源。
標記 StaticResource
延伸與 DynamicResource
標記延伸類似,這兩者都使用字典索引鍵從資源字典參考值。 不過,當標記延伸執行單一字典查閱時 StaticResource
, DynamicResource
標記延伸會維護字典索引鍵的連結。 因此,如果取代與索引鍵相關聯的字典專案,則會將變更套用至視覺專案。 這可讓應用程式進行運行時間資源變更。 如需標記延伸的詳細資訊,請參閱 XAML 標記延伸。
下列 XAML 範例示範如何取用資源,並在 中 StackLayout定義其他資源:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceDictionaryDemo.MainPage"
Title="Main page">
<StackLayout Margin="{StaticResource PageMargin}"
Spacing="6">
<StackLayout.Resources>
<!-- Implicit style -->
<Style TargetType="Button">
<Setter Property="FontSize" Value="14" />
<Setter Property="BackgroundColor" Value="#1976D2" />
<Setter Property="TextColor" Value="White" />
<Setter Property="CornerRadius" Value="5" />
</Style>
</StackLayout.Resources>
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries." />
<Button Text="Navigate"
Clicked="OnNavigateButtonClicked" />
</StackLayout>
</ContentPage>
在此範例中 ContentPage ,物件會取用應用層級資源字典中定義的隱含樣式。 物件 StackLayout 會 PageMargin
取用應用層級資源字典中定義的資源,而 Button 物件會取用資源字典中 StackLayout 定義的隱含樣式。 這會導致下列螢幕快照所示的外觀:
重要
單一頁面特有的資源不應該包含在應用層級資源字典中,例如,這些資源會在應用程式啟動時剖析,而不是當頁面需要時。 如需詳細資訊,請參閱 減少應用程式資源字典大小。
資源查閱行為
當以 或 DynamicResource
標記延伸參考StaticResource
資源時,就會發生下列查閱程式:
- 如果資源字典存在,則會針對設定 屬性的 元素檢查要求的索引鍵。 如果找到要求的索引鍵,則會傳回其值,而且查閱程式會終止。
- 如果找不到相符專案,查閱程式會向上搜尋可視化樹狀結構,並檢查每個父元素的資源字典。 如果找到要求的索引鍵,則會傳回其值,而且查閱程式會終止。 否則,進程會往上繼續,直到到達根元素為止。
- 如果在根元素上找不到相符專案,則會檢查應用層級資源字典。
- 如果仍然找不到相符專案,
XamlParseException
則會擲回 。
因此,當 XAML 剖析器遇到 StaticResource
或 DynamicResource
標記延伸時,它會使用找到的第一個比對專案,透過可視化樹狀結構移動來搜尋比對索引鍵。 如果此搜尋會在頁面結束,且索引鍵仍未找到,則 XAML 剖析器會搜尋 ResourceDictionary 附加至 App
物件的 。 如果仍然找不到索引鍵,則會擲回例外狀況。
覆寫資源
當資源分享索引鍵時,可視化樹狀結構中較低定義的資源會優先於較高定義的資源。 例如,將資源設定 AppBackgroundColor
為 AliceBlue
應用層級,將會由頁面層級 AppBackgroundColor
資源設定為 Teal
來覆寫。 同樣地,版面配置或檢視層級資源會覆寫頁面層級AppBackgroundColor
AppBackgroundColor
資源。
獨立資源字典
ResourceDictionary也可以建立 為獨立的 XAML 檔案,而該檔案不受程式代碼後置檔案支援。 若要建立獨立ResourceDictionary檔案,請使用 .NET MAUI ResourceDictionary (XAML) 專案範本將新ResourceDictionary檔案新增至專案,並刪除其程式代碼後置檔案。 然後,在 XAML 檔案中,從ResourceDictionary檔案開頭附近的標記中移除 x:Class
屬性。 此外,在 XML 標頭後面新增 <?xaml-comp compile="true" ?>
,以確保 XAML 會編譯。
ResourceDictionary也可以建立 為獨立的 XAML 檔案,而該檔案不受程式代碼後置檔案支援。 若要建立獨立ResourceDictionary檔案,請使用 .NET MAUI ResourceDictionary (XAML) 專案範本將新ResourceDictionary檔案新增至專案,並刪除其程式代碼後置檔案。 然後,在 XAML 檔案中,從ResourceDictionary檔案開頭附近的標記中移除 x:Class
屬性。 根據預設,獨立 ResourceDictionary 具有其 XAML 編譯,除非 <?xaml-comp compile="false" ?>
在 XML 標頭之後指定。
注意
獨立ResourceDictionary必須有MauiXaml的建置動作。
下列 XAML 範例顯示名為 MyResourceDictionary.xaml 的獨立ResourceDictionary:
<?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<DataTemplate x:Key="PersonDataTemplate">
<ViewCell>
<Grid RowSpacing="6"
ColumnSpacing="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}"
TextColor="{StaticResource NormalTextColor}"
FontAttributes="Bold" />
<Label Grid.Column="1"
Text="{Binding Age}"
TextColor="{StaticResource NormalTextColor}" />
<Label Grid.Column="2"
Text="{Binding Location}"
TextColor="{StaticResource NormalTextColor}"
HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
在此範例中, ResourceDictionary 包含單一資源,這是 類型的 DataTemplate物件。 MyResourceDictionary.xaml 可以藉由將它合併到另一個資源字典來取用。
合併資源字典
資源字典可以藉由將一或多個 ResourceDictionary 物件合併成另一個 ResourceDictionary來合併。
合併本機資源字典
ResourceDictionary本機檔案可以藉由建立屬性設定為具有資源之 XAML 檔案檔名的物件,以合併為另一個ResourceDictionaryResourceDictionary物件Source
:
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
此語法不會具現化 MyResourceDictionary
類別。 相反地,它會參考 XAML 檔案。 因此,在設定 Source
屬性時,不需要程式代碼後置檔案,而且x:Class
屬性可以從 MyResourceDictionary.xaml 檔案的根標記中移除。
重要
ResourceDictionary.Source
屬性只能從 XAML 設定。
從其他元件合併資源字典
ResourceDictionary也可以藉由將它加入 至 的ResourceDictionary屬性,將其合併至MergedDictionaries
另一個 ResourceDictionary 。 不論資源字典所在的元件為何,這項技術都允許合併資源字典。 從外部元件合併資源字典需要 ResourceDictionary 將組建動作設定為 MauiXaml、具有程式碼後置檔案,以及在檔案的根標記中定義 x:Class
屬性。
警告
ResourceDictionary 類別也會定義 MergedWith
屬性。 不過,這個屬性已被取代,不應再使用。
下列程式代碼範例顯示要新增至 MergedDictionaries
頁面層級 ResourceDictionary集合的兩個資源字典:
<ContentPage ...
xmlns:local="clr-namespace:ResourceDictionaryDemo"
xmlns:theme="clr-namespace:MyThemes;assembly=MyThemes">
<ContentPage.Resources>
<ResourceDictionary>
<!-- Add more resources here -->
<ResourceDictionary.MergedDictionaries>
<!-- Add more resource dictionaries here -->
<local:MyResourceDictionary />
<theme:DefaultTheme />
<!-- Add more resource dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Add more resources here -->
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
在此範例中,來自相同元件的資源字典,以及外部元件的資源字典,會合併到頁面層級資源字典中。 此外,您也可以在屬性元素標籤新增MergedDictionaries
其他ResourceDictionary物件,以及這些標籤以外的其他資源。
重要
中ResourceDictionary只能有一個MergedDictionaries
屬性元素標記,但您可以視需要將盡可能多的ResourceDictionary物件放在該處。
當合併 ResourceDictionary 的資源分享相同的 x:Key
屬性值時,.NET MAUI 會使用下列資源優先順序:
- 資源字典的本機資源。
- 透過
MergedDictionaries
集合合併之資源字典中包含的資源,會以屬性中MergedDictionaries
所列的反向順序排列。
提示
如果應用程式包含多個大型資源字典,則搜尋資源字典可能是需要大量計算的工作。 因此,為了避免不必要的搜尋,您應該確保應用程式中的每一個頁面都只會使用適合頁面的資源字典。
從程式代碼取用以 XAML 為基礎的資源字典
XAML 中定義的資源字典可以在程式代碼中取用,前提是 ResourceDictionary 由程式代碼後置檔案支援。 在 Visual Studio 中,程式代碼後置檔案所支援的 XAML 型ResourceDictionary檔案可由 .NET MAUI ResourceDictionary (XAML) 專案範本新增至您的專案:
程式代碼後置檔案所支援的 XAML 型資源字典接著可以從 C# 取用,方法是將它們新增至 MergedDictionaries 資源字典的集合:
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyColors());
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyStyles());
從程式代碼依金鑰存取資源
您可以從程式代碼存取資源字典中的資源,就像任何其他字典一樣。
下列範例示範如何從頁面的資源字典擷取和套用資源:
// Retrieve the Primary color value which is in the page's resource dictionary
var hasValue = Resources.TryGetValue("Primary", out object primaryColor);
if (hasValue)
{
myLabel.TextColor = (Color)primaryColor;
}
這是建議的方法,可確保如果 .NET MAUI 無法從程式代碼擷取資源,就不會擲回 KeyNotFoundException
。 當合併的資源字典是由 XAML 檔案中定義的資源和內嵌資源所組成時,就可能發生此情況。 如需詳細資訊,請參閱 GitHub 問題 #11214。
注意
若要從程式代碼擷取全應用程式資源,請存取 App.Current.Resources
資源字典。