Share via


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:

Consuming resource dictionary resources.

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.

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" ?>
<?xaml-comp compile="true" ?>
<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:

  1. Die lokalen Ressourcen im Ressourcenwörterbuch.
  2. Die in den Ressourcen-Wörterbüchern enthaltenen Ressourcen, die über die MergedDictionaries Sammlung zusammengeführt wurden, sind in umgekehrter Reihenfolge in der MergedDictionaries 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:

Screenshot of resource dictionaries backed by code-behind.

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.