將應用程式主題設定為
.NET 多平臺應用程式 UI (.NET MAUI) 應用程式可以使用標記延伸,在運行 DynamicResource
時間動態響應樣式變更。 這個標記延伸類似於 StaticResource
標記延伸,這兩者都使用字典索引鍵從 ResourceDictionary擷取值。 不過,當標記延伸執行單一字典查閱時 StaticResource
, DynamicResource
標記延伸會維護字典索引鍵的連結。 因此,如果已取代與索引鍵相關聯的值,則會將變更套用至 VisualElement。 這可讓運行時間主題在 .NET MAUI 應用程式中實作。
在 .NET MAUI 應用程式中實作運行時間主題的程式如下:
- 定義 中 ResourceDictionary每個主題的資源。 如需詳細資訊,請參閱 定義主題。
- 在應用程式的 App.xaml 檔案中設定預設主題。 如需詳細資訊,請參閱 設定預設主題。
- 使用標記延伸來取用
DynamicResource
應用程式中的主題資源。 如需詳細資訊,請參閱 取用主題資源。 - 新增程式代碼以在運行時間載入主題。 如需詳細資訊,請參閱 在運行時間載入主題。
重要
如果您的應用程式不需要在運行時間動態變更主題, StaticResource
請使用標記延伸。 如果您預期在應用程式執行時切換主題,請使用 DynamicResource
標記延伸,以在運行時間更新資源。
下列螢幕快照顯示主題頁面,其中 iOS 應用程式使用淺色主題和 Android 應用程式使用深色主題:
注意
在運行時間變更主題需要使用 XAML 或 C# 樣式定義,而且無法使用 CSS。
.NET MAUI 也能夠回應系統主題變更。 系統主題可能會因為各種原因而變更,視裝置組態而定。 這包括使用者明確變更的系統主題、由於一天中的時間而變更,以及由於低光等環境因素而變更。 如需詳細資訊,請參閱 響應系統主題變更。
定義主題
主題定義為儲存在中的 ResourceDictionary資源物件集合。
下列範例顯示 ResourceDictionary 名為 的 LightTheme
淺色主題的 :
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.LightTheme">
<Color x:Key="PageBackgroundColor">White</Color>
<Color x:Key="NavigationBarColor">WhiteSmoke</Color>
<Color x:Key="PrimaryColor">WhiteSmoke</Color>
<Color x:Key="SecondaryColor">Black</Color>
<Color x:Key="PrimaryTextColor">Black</Color>
<Color x:Key="SecondaryTextColor">White</Color>
<Color x:Key="TertiaryTextColor">Gray</Color>
<Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>
下列範例顯示 ResourceDictionary 名為 之 DarkTheme
深色主題的 :
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.DarkTheme">
<Color x:Key="PageBackgroundColor">Black</Color>
<Color x:Key="NavigationBarColor">Teal</Color>
<Color x:Key="PrimaryColor">Teal</Color>
<Color x:Key="SecondaryColor">White</Color>
<Color x:Key="PrimaryTextColor">White</Color>
<Color x:Key="SecondaryTextColor">White</Color>
<Color x:Key="TertiaryTextColor">WhiteSmoke</Color>
<Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>
每個 ResourceDictionary 都包含 Color 定義其個別主題的資源,且每個資源都 ResourceDictionary 使用相同的索引鍵值。 如需資源字典的詳細資訊,請參閱 資源字典。
重要
每個 ResourceDictionary都需要檔案後置程序代碼,其會呼叫 InitializeComponent
方法。 這是必要的,如此一來,就可以在運行時間建立代表所選主題的CLR物件。
設定預設主題
應用程式需要默認主題,讓控件具有其取用資源的值。 您可以將主題ResourceDictionary合併為 App.xaml 中定義的應用程式層級ResourceDictionary,以設定預設主題:
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.App">
<Application.Resources>
<ResourceDictionary Source="Themes/LightTheme.xaml" />
</Application.Resources>
</Application>
如需合併資源字典的詳細資訊,請參閱 合併的資源字典。
取用主題資源
當應用程式想要取用儲存在 ResourceDictionary 中代表主題的資源時,應該使用 DynamicResource
標記延伸來執行此動作。 這可確保如果在運行時間選取不同的主題,則會套用新主題中的值。
下列範例顯示三種樣式,可套用至應用程式中的所有 Label 物件:
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.App">
<Application.Resources>
<Style x:Key="LargeLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource SecondaryTextColor}" />
<Setter Property="FontSize"
Value="30" />
</Style>
<Style x:Key="MediumLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="FontSize"
Value="25" />
</Style>
<Style x:Key="SmallLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource TertiaryTextColor}" />
<Setter Property="FontSize"
Value="15" />
</Style>
</Application.Resources>
</Application>
這些樣式是在應用層級資源字典中定義,以便可供多個頁面取用。 每個樣式都會使用 DynamicResource
標記延伸的主題資源。
這些樣式接著會由頁面取用:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ThemingDemo"
x:Class="ThemingDemo.UserSummaryPage"
Title="User Summary"
BackgroundColor="{DynamicResource PageBackgroundColor}">
...
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="120" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid BackgroundColor="{DynamicResource PrimaryColor}">
<Label Text="Face-Palm Monkey"
VerticalOptions="Center"
Margin="15"
Style="{StaticResource MediumLabelStyle}" />
...
</Grid>
<StackLayout Grid.Row="1"
Margin="10">
<Label Text="This monkey reacts appropriately to ridiculous assertions and actions."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Cynical but not unfriendly."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Seven varieties of grimaces."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Doesn't laugh at your jokes."
Style="{StaticResource SmallLabelStyle}" />
</StackLayout>
...
</Grid>
</ScrollView>
</ContentPage>
直接取用主題資源時,應該使用標記延伸來取用 DynamicResource
。 不過,當使用標記延伸的DynamicResource
樣式使用時,應該使用標記延伸。StaticResource
如需樣式的詳細資訊,請參閱 使用 XAML 設定應用程式樣式。 如需標記延伸的詳細資訊 DynamicResource
,請參閱 動態樣式。
在運行時間載入主題
在執行時間選取主題時,應用程式應該:
- 從應用程式移除目前的主題。 這可藉由清除
MergedDictionaries
應用層級 ResourceDictionary的屬性來達成。 - 載入選取的主題。 這可藉由將所選主題的實例新增至
MergedDictionaries
應用層級 ResourceDictionary的屬性來達成。
任何 VisualElement 使用 DynamicResource
標記延伸設定屬性的對象,都會套用新的主題值。 這是因為 DynamicResource
標記延伸會維護字典索引鍵的連結。 因此,當取代與索引鍵相關聯的值時,這些變更會套用至 VisualElement 物件。
在範例應用程式中,會透過包含 Picker的強制回應頁面選取主題。 下列程式代碼顯示 OnPickerSelectionChanged
方法,這個方法會在選取的主題變更時執行:
下列範例顯示移除目前的主題並載入新主題:
ICollection<ResourceDictionary> mergedDictionaries = Application.Current.Resources.MergedDictionaries;
if (mergedDictionaries != null)
{
mergedDictionaries.Clear();
mergedDictionaries.Add(new DarkTheme());
}