Ressourcenverzeichnisse
Eine .NET Multi-Platform App UI (.NET MAUI) ResourceDictionary ist ein Speicher für Ressourcen, die von einer .NET MAUI-App verwendet werden. Typische Ressourcen, die in einem ResourceDictionary gespeichert sind, umfassen Formatvorlagen, Steuerelementvorlagen, Datenvorlagen, Konverter und Farben.
XAML-Ressourcen, die in einem ResourceDictionary gespeichert sind, können mit der Markup-Erweiterung StaticResource
oder DynamicResource
referenziert und auf Elemente angewendet werden. In C# können Ressourcen auch in einem ResourceDictionary definiert werden und dann mit Hilfe eines stringbasierten Indexers auf Elemente verwiesen und angewendet werden.
Tipp
In Visual Studio kann eine XAML-basierte ResourceDictionary Datei, die von einer Code-Behind-Datei unterstützt wird, über die .NET MAUI ResourceDictionary (XAML) Elementvorlage zu Ihrem Projekt hinzugefügt werden.
Erstellen von Ressourcen
Jedes VisualElement abgeleitete Objekt verfügt über eine Resources
Eigenschaft, die eine ResourceDictionary ist und Ressourcen enthalten kann. Ebenso verfügt ein abgeleitetes Application
Objekt über eine Resources
Eigenschaft, die ResourceDictionary Ressourcen enthalten kann.
Eine .NET-MAUI-Anwendung kann nur eine einzige Klasse enthalten, die von Application
abgeleitet ist, verwendet aber oft viele Klassen, die von VisualElement abgeleitet sind, einschließlich Seiten, Layouts und Ansichten. Jedes dieser Objekte kann seine Resources
Eigenschaft auf eine ResourceDictionary enthaltende Ressource festlegen. Die Wahl des Ortes, an dem ein bestimmtes ResourceDictionary abgelegt wird, hat Auswirkungen darauf, wo die Ressourcen verwendet werden können:
- Ressourcen in einer ResourceDictionary, die an eine Ansicht angefügt sind, wie etwa Button oder Label, können nur auf dieses bestimmte Objekt angewendet werden.
- Ressourcen in einem ResourceDictionary, das einem Layout zugeordnet ist, wie StackLayout oder Grid, können auf das Layout und alle untergeordneten Elemente dieses Layouts angewendet werden.
- Ressourcen in einer ResourceDictionary, die auf Seitenebene definiert sind, können auf die Seite und alle ihre Unterseiten angewendet werden.
- Ressourcen in einer ResourceDictionary definiert auf der Anwendungsebene können auf die gesamte App angewendet werden.
Mit Ausnahme von impliziten Stilen muss jede Ressource im Ressourcenwörterbuch einen eindeutigen String-Schlüssel haben, der mit dem Attribut x:Key
definiert wird.
Der folgende XAML zeigt Ressourcen, die in einer Anwendungsebene ResourceDictionary in der Datei App.xaml definiert sind:
<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>
In diesem Beispiel definiert das Ressourcenverzeichnis eine Thickness
Ressource, mehrere Color Ressourcen und zwei implizite Style Ressourcen.
Wichtig
Das Einfügen von Ressourcen direkt zwischen den Resources
Property-Element-Tags erzeugt automatisch ein ResourceDictionary Objekt. Es ist jedoch auch gültig, alle Ressourcen zwischen optionalen ResourceDictionary Tags zu platzieren.
Ressourcen verbrauchen
Jede Ressource verfügt über einen Schlüssel, der mithilfe des x:Key
Attributs angegeben wird, das zu seinem Wörterbuchschlüssel in der ResourceDictionary wird. Der Schlüssel wird verwendet, um auf eine Ressource aus der ResourceDictionary mit der StaticResource
oder DynamicResource
XAML-Markuperweiterung zu verweisen.
Die Markup-Erweiterung StaticResource
ähnelt der Markup-Erweiterung DynamicResource
insofern, als beide einen Wörterbuchschlüssel verwenden, um auf einen Wert aus einem Ressourcenwörterbuch zu verweisen. Während die Markup-Erweiterung StaticResource
jedoch nur eine einzige Wörterbuchsuche durchführt, behält die Markup-Erweiterung DynamicResource
eine Verknüpfung mit dem Wörterbuchschlüssel bei. Wenn also der mit dem Schlüssel verbundene Wörterbucheintrag ersetzt wird, wird die Änderung auf das visuelle Element angewendet. Dadurch können Laufzeitressourcen-Änderungen in einer App vorgenommen werden. Weitere Informationen über -Markup-Erweiterungen finden Sie unter XAML-Markup-Erweiterungen.
Das folgende XAML Beispiel zeigt, wie man Ressourcen verbraucht und eine zusätzliche Ressource in einem StackLayout definiert:
<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>
In diesem Beispiel verwendet das ContentPage Objekt die implizite Formatvorlage, die im Ressourcenverzeichnis auf Anwendungsebene definiert ist. Das StackLayout Objekt verwendet die PageMargin
im Ressourcenverzeichnis auf Anwendungsebene definierte Ressource, während das Button Objekt den im StackLayout Ressourcenwörterbuch definierten impliziten Stil verwendet. Dies ergibt die im folgenden Screenshot gezeigte Darstellung:
Wichtig
Ressourcen, die für eine einzelne Seite spezifisch sind, sollten nicht in ein Ressourcenwörterbuch auf Anwendungsebene aufgenommen werden, da solche Ressourcen dann beim Start der Anwendung ausgelesen werden, anstatt wenn sie von einer Seite benötigt werden. Weitere Informationen finden Sie unter Verringern der Größe des Ressourcenverzeichnisses der Anwendung.
Suchverhalten von Ressourcen
Der folgende Nachschlagevorgang tritt auf, wenn eine Ressource mit der StaticResource
oder DynamicResource
Markup-Erweiterung referenziert wird:
- Die Suche prüft den angeforderten Schlüssel im Ressourcenverzeichnis, der durch das Element definiert wird, welches die Eigenschaft festlegt: Wenn der angeforderte Schlüssel gefunden wird, wird der Wert zurückgegeben, und der Nachschlagevorgang wird beendet.
- Wenn keine Übereinstimmung gefunden wird, durchsucht der Nachschlagevorgang die visuelle Struktur nach oben, und überprüft das Ressourcenverzeichnis jedes übergeordneten Elements. Wenn der angeforderte Schlüssel gefunden wird, wird der Wert zurückgegeben, und der Nachschlagevorgang wird beendet. Andernfalls wird dieser Vorgang fortgesetzt, bis das Basiselelement erreicht ist.
- Wenn eine Übereinstimmung nicht im Basiselement gefunden wird, wird das Ressourcenverzeichnis auf Anwendungsebene untersucht.
- Wenn eine Übereinstimmung immer noch nicht gefunden wird, wird ein
XamlParseException
Fehler ausgelöst.
Wenn also der XAML-Parser auf eine StaticResource
oder DynamicResource
Markup-Erweiterung stößt, sucht er nach einem passenden Schlüssel, indem er den visuellen Baum nach oben durchläuft und die erste gefundene Übereinstimmung verwendet. Wenn diese Suche auf der Seite endet und der Schlüssel noch nicht gefunden wurde, durchsucht der XAML Parser das ResourceDictionary angefügt an das App
Objekt. Wenn der Schlüssel immer noch nicht gefunden wird, wird eine Ausnahme ausgelöst.
Außerkraftsetzung von Ressourcen
Wenn Ressourcen Schlüssel gemeinsam nutzen, haben Ressourcen, die in der visuellen Struktur niedriger definiert sind, Vorrang vor den darüber definierten Ressourcen. Wenn beispielsweise eine AppBackgroundColor
Ressource auf der Anwendungsebene auf AliceBlue
gesetzt wird, wird sie von einer AppBackgroundColor
Ressource auf Seitenebene, die auf Teal
gesetzt ist, überschrieben. Ebenso wird eine Ressource auf Seitenebene AppBackgroundColor
überschrieben durch eine Layout- oder Ansichtsebenen AppBackgroundColor
Ressource.
Eigenständige Ressourcenverzeichnisse
Eine ResourceDictionary kann auch als eigenständige XAML Datei erstellt werden, die nicht von einer CodeBehind-Datei unterstützt wird. Zur Erstellung einer eigenständigen ResourceDictionary fügen Sie dem Projekt eine neue ResourceDictionary Datei mit der Elementvorlage .NET MAUI ResourceDictionary (XAML) hinzu und löschen die Code-Behind-Datei. Entfernen Sie dann in der XAML-Datei das Attribut x:Class
aus dem ResourceDictionary Tag in der Nähe des Dateianfangs. Zusätzlich fügen Sie <?xaml-comp compile="true" ?>
nach dem XML-Header hinzu, um sicherzustellen, dass der XAML kompiliert wird.
Eine ResourceDictionary kann auch als eigenständige XAML Datei erstellt werden, die nicht von einer CodeBehind-Datei unterstützt wird. Zur Erstellung einer eigenständigen ResourceDictionary fügen Sie dem Projekt eine neue ResourceDictionary Datei mit der Elementvorlage .NET MAUI ResourceDictionary (XAML) hinzu und löschen die Code-Behind-Datei. Entfernen Sie dann in der XAML-Datei das Attribut x:Class
aus dem ResourceDictionary Tag in der Nähe des Dateianfangs. Standardmäßig wird bei einem eigenständigen ResourceDictionary die XAML kompiliert, es sei denn, <?xaml-comp compile="false" ?>
wird nach dem XML-Header angegeben.
Hinweis
Eine eigenständige ResourceDictionary muss eine Erstellungsaktion von MauiXaml haben.
Das folgende XAML-Beispiel zeigt ein eigenständiges ResourceDictionary bezeichnetes MyResourceDictionary.xaml:
<?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>
In diesem Beispiel enthält die ResourceDictionary eine einzelne Ressource, bei der es sich um ein Objekt vom Typ DataTemplate handelt. MyResourceDictionary.xaml kann genutzt werden, indem es in ein anderes Ressourcenwörterbuch zusammengeführt wird.
Zusammenführung von Ressourcenverzeichnissen
Ressourcenwörterbücher können kombiniert werden, indem ein oder mehrere ResourceDictionary Objekte in ein anderes ResourceDictionary zusammengeführt werden.
Lokale Ressourcenwörterbücher zusammenführen
Eine lokale ResourceDictionary Datei kann in eine andere ResourceDictionary Datei zusammengeführt werden, indem ein ResourceDictionary Objekt erstellt wird, dessen Source
Eigenschaft auf den Dateinamen der XAML Datei mit den Ressourcen gesetzt wird:
<ContentPage ...>
<ContentPage.Resources>
<!-- Add more resources here -->
<ResourceDictionary Source="MyResourceDictionary.xaml" />
<!-- Add more resources here -->
</ContentPage.Resources>
...
</ContentPage>
Diese Syntax instanziiert die MyResourceDictionary
Klasse nicht. Stattdessen verweist sie auf die XAML Datei. Aus diesem Grund ist beim Festlegen der Source
Eigenschaft keine CodeBehind-Datei erforderlich, und das x:Class
Attribut kann aus dem Stammtag der MyResourceDictionary.xaml Datei entfernt werden.
Wichtig
Die ResourceDictionary.Source
Eigenschaft kann nur aus XAML festgelegt werden.
Zusammenführen von Ressourcenwörterbüchern aus anderen Baugruppen
Ein ResourceDictionary kann auch mit einem anderen ResourceDictionary verschmolzen werden, indem es in die MergedDictionaries
Eigenschaft des ResourceDictionary eingefügt wird. Mit dieser Technik können Ressourcenwörterbücher zusammengeführt werden, unabhängig von der Baugruppe, in der sie sich befinden. Das Zusammenführen von Ressourcen-Wörterbüchern aus externen Baugruppen erfordert, dass die ResourceDictionary Erstellungsaktion auf MauiXaml gesetzt ist, dass eine Code-Behind-Datei vorhanden ist und dass das x:Class
Attribut im Root-Tag der Datei definiert ist.
Warnung
Die ResourceDictionary-Klasse definiert ebenfalls eine MergedWith
-Eigenschaft. Diese Eigenschaft ist jedoch veraltet und sollte nicht mehr verwendet werden.
Das folgende Codebeispiel zeigt, wie zwei Ressourcenwörterbücher der MergedDictionaries
Sammlung einer Seitenebene ResourceDictionary hinzugefügt werden:
<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>
In diesem Beispiel werden ein Ressourcenwörterbuch aus derselben Baugruppe und ein Ressourcenwörterbuch aus einer externen Baugruppe in das Ressourcenverzeichnis auf Seitenebene zusammengeführt. Darüber hinaus können Sie auch andere ResourceDictionary Objekte innerhalb der MergedDictionaries
Eigenschaftselementtags und andere Ressourcen außerhalb dieser Tags hinzufügen.
Wichtig
Es kann nur ein MergedDictionaries
Eigenschaftselement-Tag geben in einem ResourceDictionary , aber Sie können so viele ResourceDictionary-Objekte darin unterbringen wie nötig.
Wenn zusammengeführte ResourceDictionary Ressourcen identische x:Key
Attributwerte aufweisen, verwendet .NET MAUI die folgende Rangfolge der Ressourcen:
- Die lokalen Ressourcen im Ressourcenwörterbuch.
- Die in den Ressourcen-Wörterbüchern enthaltenen Ressourcen, die über die
MergedDictionaries
Sammlung zusammengeführt wurden, sind in umgekehrter Reihenfolge in derMergedDictionaries
Eigenschaft aufgeführt.
Tipp
Das Durchsuchen von Ressourcenwörterbüchern kann eine rechenintensive Aufgabe sein, wenn eine App mehrere, große Ressourcenwörterbücher enthält. Um unnötige Suche zu vermeiden, sollten Sie daher sicherstellen, dass jede Seite in einer Anwendung nur Ressourcenwörterbücher verwendet, die für die Seite geeignet sind.
Ein XAML basiertes Ressourcenverzeichnis aus dem Code heraus konsumieren
Ressourcenwörterbücher, die in XAML definiert sind, können im Code verwendet werden, sofern das ResourceDictionary durch eine CodeBehind-Datei gesichert wird. In Visual Studio können XAML-basierte ResourceDictionary Dateien, die durch Code-Behind-Dateien unterstützt werden, über die .NET MAUI ResourceDictionary (XAML) Elementvorlage zu Ihrem Projekt hinzugefügt werden:
XAML-basierte Ressourcenwörterbücher, die von CodeBehind-Dateien unterstützt werden, können dann von C# verwendet werden, indem Sie sie zur MergedDictionaries Sammlung des Ressourcenwörterbuchs hinzufügen:
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyColors());
Resources.MergedDictionaries.Add(new MyMauiApp.Resources.Styles.MyStyles());
Zugriff auf Ressourcen durch Schlüssel aus dem Code
Sie können über Code wie jedes andere Wörterbuch auf Ressourcen in einem Ressourcenwörterbuch zugreifen.
Das folgende Beispiel zeigt, wie Sie eine Ressource aus dem Ressourcenverzeichnis einer Seite abrufen und anwenden:
// 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;
}
Dies ist der empfohlene Ansatz, der sicherstellt, dass .NET MAUI keine KeyNotFoundException
auslöst, wenn eine Ressource nicht aus dem Code abgerufen werden kann. Dies kann auftreten, wenn ein zusammengeführtes Ressourcenverzeichnis aus Ressourcen besteht, die in einer XAML-Datei und Inline-Ressourcen definiert sind. Weitere Informationen finden Sie unter GitHub Issue #11214.
Hinweis
Um appweite Ressourcen aus dem Code abzurufen, greifen Sie auf das App.Current.Resources
-Ressourcenverzeichnis zu.