Designen einer App
.NET Multi-Platform App UI (.NET MAUI)-Apps können durch die Verwendung der DynamicResource
-Markuperweiterung dynamisch auf Stiländerungen zur Laufzeit reagieren. Diese Markuperweiterung ist der StaticResource
-Markuperweiterung insofern ähnlich, als beide einen Wörterbuchschlüssel verwenden, um einen Wert aus einem ResourceDictionary zu extrahieren. Während die StaticResource
-Markuperweiterung eine einzelne Wörterbuchsuche durchführt, behält die DynamicResource
-Markuperweiterung einen Link zum Wörterbuchschlüssel bei. Wenn also der dem Schlüssel zugeordnete Wert ersetzt wird, wird die Änderung auf das VisualElement angewendet. Dadurch können Laufzeitdesigns in .NET MAUI-Apps implementiert werden.
Der Prozess für die Implementierung des Laufzeitdesigns in einer .NET MAUI-App läuft wie folgt ab:
- Definieren Sie die Ressourcen für jedes Design in einem ResourceDictionary. Weitere Informationen finden Sie unter Definieren von Designs.
- Legen Sie in der Datei App.xaml der App ein Standarddesign fest. Weitere Informationen finden Sie unter Festlegen eines Standarddesigns.
- Verwenden Sie Designressourcen in der App mithilfe der
DynamicResource
-Markuperweiterung. Weitere Informationen finden Sie unter Verwenden von Designressourcen. - Fügen Sie Code hinzu, um ein Design zur Laufzeit zu laden. Weitere Informationen finden Sie unter Laden eines Designs zur Laufzeit.
Wichtig
Verwenden Sie die StaticResource
-Markuperweiterung, wenn Ihre App die Themen nicht dynamisch zur Laufzeit ändern muss. Wenn Sie während der Ausführung der App das Wechseln von Designs antizipieren, verwenden Sie die DynamicResource
-Markuperweiterung, wodurch Ressourcen zur Laufzeit aktualisiert werden können.
Der folgende Screenshot zeigt Design-Seiten, wobei die iOS-App ein helles Design und die Android-App ein dunkles Design verwendet:
Hinweis
Das Ändern eines Themas zur Laufzeit erfordert die Verwendung von XAML- oder C#-Stildefinitionen und ist mit CSS nicht möglich.
.NET MAUI bietet auch die Möglichkeit, auf Systemdesignänderungen zu reagieren. Das Systemdesign kann sich je nach Gerätekonfiguration aus verschiedenen Gründen ändern. Dazu gehören die explizite Änderung des Systemdesigns durch den Benutzer*innen, die Änderung des Systemdesigns aufgrund der Tageszeit und die Änderung des Systemdesigns aufgrund von Umgebungsfaktoren wie z. B. schlechte Lichtverhältnisse. Weitere Informationen finden Sie unter Reagieren auf Änderungen des Systemdesigns.
Definieren von Designs
Ein Design wird als eine Sammlung von Ressourcenobjekten definiert, die in einem ResourceDictionary gespeichert sind.
Das folgende Beispiel zeigt ein helles Design namens LightTheme
in einem ResourceDictionary:
<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>
Das folgende Beispiel zeigt ein dunkles Design namens DarkTheme
in einem ResourceDictionary:
<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>
Jedes ResourceDictionary enthält Color-Ressourcen, die ihre jeweiligen Designs definieren, wobei jedes ResourceDictionary identische Schlüsselwerte verwendet. Weitere Informationen zu Ressourcenverzeichnissen finden Sie unter Ressourcenverzeichnisse.
Wichtig
Für jedes ResourceDictionary, das die InitializeComponent
-Methode aufruft, ist eine CodeBehind-Datei erforderlich. Nur so kann zur Laufzeit ein CLR-Objekt erstellt werden, das das ausgewählte Design repräsentiert.
Festlegen eines Standarddesigns
Ein Standarddesign wird für eine App benötigt, damit die Steuerelemente Werte für die Ressourcen haben, die sie verwenden. Ein Standarddesign kann festgelegt werden, indem das ResourceDictionary des Designs in die App.xaml definierte ResourceDictionary-App-Ebene eingebunden wird:
<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>
Weitere Informationen zum Zusammenführen von Ressourcenverzeichnissen finden Sie unter Zusammengeführte Ressourcenverzeichnisse.
Verwenden von Designressourcen
Wenn eine App eine Ressource verwenden möchte, die in einem ResourceDictionary gespeichert ist, das ein Design darstellt, sollte dies mit der DynamicResource
-Markuperweiterung erfolgen. Dadurch wird sichergestellt, dass bei der Auswahl eines anderen Designs zur Laufzeit die Werte des neuen Designs verwendet werden.
Das folgende Beispiel zeigt drei Formatvorlagen, die auf alle Label-Objekte in der App angewendet werden können:
<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>
Diese Formatvorlagen werden im Ressourcenverzeichnis auf App-Ebene definiert, sodass sie von mehreren Seiten verwendet werden können. Jede Formatvorlage verwendet Designressourcen mit der DynamicResource
-Markuperweiterung.
Diese Formatvorlagen werden dann von Seiten verwendet:
<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>
Wenn eine Designressource direkt verwendet wird, sollte dies mit der DynamicResource
-Markuperweiterung geschehen. Wenn jedoch eine Formatvorlage verwendet wird, die die DynamicResource
-Markuperweiterung verwendet, sollte dies mit der StaticResource
-Markuperweiterung geschehen.
Weitere Informationen zum Formatieren finden Sie unter Formatieren von Apps mit XAML. Weitere Informationen zur DynamicResource
-Markuperweiterung finden Sie unter Dynamische Formatvorlagen.
Laden eines Designs während der Laufzeit
Wenn ein Design während der Laufzeit ausgewählt wird, sollte eine App Folgendes ausführen:
- Das aktuelle Design aus der App entfernen. Dies wird erreicht, indem die
MergedDictionaries
-Eigenschaft des ResourceDictionary auf App-Ebene gelöscht wird. - Das ausgewählte Design laden. Dies wird durch Hinzufügen einer Instanz des ausgewählten Designs zur
MergedDictionaries
-Eigenschaft des ResourceDictionary auf App-Ebene erreicht.
Alle VisualElement-Objekte, die Eigenschaften mit der DynamicResource
-Markuperweiterung festlegen, wenden dann die neuen Designwerte an. Dies geschieht, da die DynamicResource
-Markuperweiterung einen Link zu Verzeichnisschlüsseln enthält. Wenn die mit Schlüsseln verknüpften Werte ersetzt werden, werden die Änderungen daher auf die VisualElement-Objekte angewendet.
In der Beispielanwendung wird ein Design über eine modale Seite ausgewählt, die einen Picker enthält. Der folgende Code zeigt die OnPickerSelectionChanged
-Methode, die ausgeführt wird, wenn sich das ausgewählte Design ändert:
Im folgenden Beispiel wird das aktuelle Design entfernt und ein neues Design geladen:
ICollection<ResourceDictionary> mergedDictionaries = Application.Current.Resources.MergedDictionaries;
if (mergedDictionaries != null)
{
mergedDictionaries.Clear();
mergedDictionaries.Add(new DarkTheme());
}