Freigeben über


Xamarin.Forms Ressourcenwörterbücher

A ResourceDictionary ist ein Repository für Ressourcen, die von einer Xamarin.Forms Anwendung verwendet werden. Typische Ressourcen, die in einem ResourceDictionary Format gespeichert sind, umfassen Formatvorlagen, Steuerelementvorlagen, Datenvorlagen, Farben und Konverter.

In XAML können ressourcen, die in einer ResourceDictionary gespeichert sind, mithilfe der StaticResource Erweiterung oder DynamicResource Markuperweiterung auf Elemente verwiesen und 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. Es gibt jedoch wenig Vorteile bei der Verwendung einer ResourceDictionary In C#, da freigegebene Objekte als Felder oder Eigenschaften gespeichert werden können und direkt darauf zugegriffen werden kann, ohne sie zuerst aus einem Wörterbuch abrufen zu müssen.

Erstellen von Ressourcen in XAML

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 Xamarin.Forms Anwendung enthält nur Eine Klasse, die von Applicationdieser abgeleitet wird, verwendet jedoch häufig viele Klassen, die von VisualElementSeiten, Layouts und Steuerelementen abgeleitet werden. 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 Ansicht, die an eine Ansicht angefügt ist, z Button . B. oder Label können nur auf dieses bestimmte Objekt angewendet werden.
  • Ressourcen in einem an ein ResourceDictionary Layout angefügten Layout, StackLayout z. B. 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, ResourceDictionary die auf Anwendungsebene definiert sind, können in der gesamten Anwendung 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://xamarin.com/schemas/2014/forms"
             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>

        <!-- Implicit styles -->
        <Style TargetType="{x:Type NavigationPage}">
            <Setter Property="BarBackgroundColor"
                    Value="{StaticResource NavigationBarColor}" />
            <Setter Property="BarTextColor"
                    Value="{StaticResource NavigationBarTextColor}" />
        </Style>

        <Style TargetType="{x:Type 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. Weitere Informationen zur App Klasse finden Sie unter Xamarin.Forms App-Klasse.

Hinweis

Es ist auch gültig, alle Ressourcen zwischen expliziten ResourceDictionary Tags zu platzieren. Da Xamarin.Forms jedoch 3.0 die ResourceDictionary Tags nicht erforderlich sind. Stattdessen wird das ResourceDictionary Objekt automatisch erstellt, und Sie können die Ressourcen direkt zwischen den Resources Eigenschaftselementtags einfügen.

Ressourcen in XAML nutzen

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 Mit- ResourceDictionary StaticResource oder DynamicResource 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 Anwendung vorgenommen werden. Weitere Informationen zu Markuperweiterungen finden Sie unter XAML-Markuperweiterungen.

Das folgende XAML-Beispiel zeigt, wie Ressourcen verbraucht werden, und definiert auch zusätzliche Ressourcen in einer StackLayout:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ResourceDictionaryDemo.HomePage"
             Title="Home Page">
    <StackLayout Margin="{StaticResource PageMargin}">
        <StackLayout.Resources>
            <!-- Implicit style -->
            <Style TargetType="Button">
                <Setter Property="FontSize" Value="Medium" />
                <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 in den folgenden Screenshots gezeigte Darstellung:

Verwenden von ResourceDictionary-Ressourcen

Wichtig

Ressourcen, die für eine einzelne Seite spezifisch sind, sollten nicht in ein Ressourcenverzeichnis auf Anwendungsebene einbezogen werden, da ressourcen dann beim Starten der Anwendung analysiert werden, statt wenn eine Seite erforderlich ist. Weitere Informationen finden Sie unter Verringern der Größe des Anwendungsressourcenwörterbuchs.

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 Ressourcen auf Seitenebene AppBackgroundColor von einer Ressource auf Steuerelementebene AppBackgroundColor überschrieben.

Eigenständige Ressourcenverzeichnisse

Eine von dieser ResourceDictionary abgeleitete Klasse kann sich auch in einer eigenständigen XAML-Datei befinden. Die XAML-Datei kann dann zwischen Anwendungen freigegeben werden.

Um eine solche Datei zu erstellen, fügen Sie dem Projekt ein neues Inhaltsansichts - oder Inhaltsseitenelement hinzu (jedoch keine Inhaltsansicht oder Inhaltsseite mit nur einer C#-Datei). Löschen Sie die CodeBehind-Datei, und ändern Sie in der XAML-Datei den Namen der Basisklasse von ContentView oder ContentPage in ResourceDictionary. Entfernen Sie außerdem das x:Class Attribut aus dem Stammtag der Datei.

Das folgende XAML-Beispiel zeigt einen ResourceDictionary Namen namens "MyResourceDictionary.xaml":

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <DataTemplate x:Key="PersonDataTemplate">
        <ViewCell>
            <Grid>
                <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.

Standardmäßig entfernt der Linker eigenständige XAML-Dateien aus Releasebuilds, wenn das Linkerverhalten so festgelegt ist, dass alle Assemblys verknüpft werden. So stellen Sie sicher, dass eigenständige XAML-Dateien in einem Releasebuild verbleiben:

  1. Fügen Sie der Assembly ein benutzerdefiniertes Preserve Attribut hinzu, das die eigenständigen XAML-Dateien enthält. Weitere Informationen finden Sie unter Beibehalten von Code.

  2. Legen Sie das Preserve Attribut auf Assemblyebene fest:

    [assembly:Preserve(AllMembers = true)]
    

Weitere Informationen zum Verknüpfen finden Sie unter "Verknüpfen von Xamarin.iOS-Apps und Verknüpfen unter Android".

Zusammengeführte Ressourcenwörterbücher

Zusammengeführte Ressourcenwörterbücher kombinieren ein oder ResourceDictionary mehrere Objekte in einem anderen ResourceDictionary.

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 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. Für das ResourceDictionary Zusammenführen von Ressourcenwörterbüchern aus externen Assemblys muss eine Buildaktion auf "EmbeddedResource" festgelegt sein, eine CodeBehind-Datei vorhanden sein und das x:Class Attribut im Stammtag der Datei definiert werden.

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:LightTheme />
                <!-- 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 gemeinsam nutzen, Xamarin.Forms wird die folgende Ressourcenrangfolge verwendet:

  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.

Hinweis

Das Durchsuchen von Ressourcenwörterbüchern kann eine rechenintensive Aufgabe sein, wenn eine Anwendung 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.

Auf Channel 9 und auf YouTube finden Sie weitere Videos zu Xamarin.