Xamarin.Forms Ressourcenwörterbücher

Beispiel herunterladen Das Beispiel herunterladen

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

In XAML können Ressourcen, die in einem ResourceDictionary gespeichert sind, mithilfe der StaticResource Markuperweiterung oder DynamicResource auf Elemente angewendet werden. In C# können Ressourcen auch in einem ResourceDictionary definiert und dann mithilfe eines Zeichenfolgen-basierten Indexers auf Elemente verwiesen und auf diese angewendet werden. Die Verwendung von in ResourceDictionary C# hat jedoch wenig Vorteile, da freigegebene Objekte als Felder oder Eigenschaften gespeichert und direkt darauf zugegriffen werden können, 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 Ressourcen ResourceDictionary enthalten kann. Auf ähnliche Weise verfügt ein abgeleitetes Application Objekt über eine Resources -Eigenschaft, die Ressourcen ResourceDictionary enthalten kann.

Eine Xamarin.Forms Anwendung enthält nur eine Klasse, die von abgeleitet wird Application, verwendet aber häufig viele Klassen, die von abgeleitet werden VisualElement, einschließlich Seiten, Layouts und Steuerelementen. Für jedes dieser Objekte kann seine Resources -Eigenschaft auf eine ResourceDictionary enthaltende Ressource festgelegt sein. Wählen Sie aus, wo ein bestimmter ResourceDictionary Ort eingesetzt werden soll, wo die Ressourcen verwendet werden können:

  • Ressourcen in einer ResourceDictionary , die einer Ansicht wie Button oder Label angefügt ist, können nur auf dieses bestimmte Objekt angewendet werden.
  • Ressourcen in einem ResourceDictionary , die an ein Layout StackLayout wie oder Grid angefügt sind, können auf das Layout und alle untergeordneten Elemente dieses Layouts angewendet werden.
  • Ressourcen in einem ResourceDictionary definierten auf Seitenebene können auf die Seite und alle untergeordneten Elemente angewendet werden.
  • Ressourcen in einem ResourceDictionary auf Anwendungsebene definierten können in der gesamten Anwendung angewendet werden.

Mit Ausnahme impliziter Stile muss jede Ressource im Ressourcenwörterbuch über einen eindeutigen Zeichenfolgenschlüssel verfügen, der mit dem x:Key -Attribut definiert ist.

Der folgende XAML-Code 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 Ressourcenwörterbuch 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. Seit Xamarin.Forms 3.0 sind die ResourceDictionary Tags jedoch nicht erforderlich. 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 ihrem Wörterbuchschlüssel in wird ResourceDictionary. Der Schlüssel wird verwendet, um auf eine Ressource von mit der ResourceDictionaryStaticResource -Markuperweiterung oder DynamicResource zu verweisen.

Die StaticResource Markuperweiterung ähnelt der DynamicResource Markuperweiterung, da beide einen Wörterbuchschlüssel verwenden, um auf einen Wert aus einem Ressourcenwörterbuch zu verweisen. Während die StaticResource Markuperweiterung jedoch eine einzelne Wörterbuchsuche durchführt, behält die DynamicResource Markuperweiterung einen Link zum Wörterbuchschlüssel bei. Wenn daher der dem Schlüssel zugeordnete 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 verwendet werden, und definiert auch zusätzliche Ressourcen in :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 nutzt das -Objekt den ContentPage impliziten Stil, der im Ressourcenverzeichnis auf Anwendungsebene definiert ist. Das StackLayout -Objekt nutzt die PageMargin im Ressourcenverzeichnis auf Anwendungsebene definierte Ressource, während das Objekt den Button impliziten Stil verwendet, der StackLayout im Ressourcenwörterbuch definiert ist. Dies ergibt die in den folgenden Screenshots gezeigte Darstellung:

Verbrauch von ResourceDictionary-Ressourcen

Wichtig

Ressourcen, die für eine einzelne Seite spezifisch sind, sollten nicht in ein Ressourcenverzeichnis auf Anwendungsebene einbezogen werden, da diese Ressourcen dann beim Start der Anwendung analysiert werden, anstatt bei Bedarf durch eine Seite. Weitere Informationen finden Sie unter Reduzieren der Größe des Anwendungsressourcenwörterbuchs.

Verhalten der Ressourcensuche

Der folgende Nachschlagevorgang tritt auf, wenn mit der StaticResource Markuperweiterung oder DynamicResource auf eine Ressource verwiesen wird:

  • Der angeforderte Schlüssel wird im Ressourcenwörterbuch für das -Element, das die -Eigenschaft festlegt, überprüft, sofern er vorhanden ist. Wenn der angeforderte Schlüssel gefunden wird, wird sein Wert zurückgegeben, und der Nachschlagevorgang wird beendet.
  • Wenn keine Übereinstimmung gefunden wird, durchsucht der Nachschlageprozess die visuelle Struktur nach oben und überprüft das Ressourcenverzeichnis jedes übergeordneten Elements. Wenn der angeforderte Schlüssel gefunden wird, wird sein Wert zurückgegeben, und der Nachschlagevorgang wird beendet. Andernfalls wird der Prozess nach oben fortgesetzt, bis das Stammelement erreicht ist.
  • Wenn im Stammelement keine Übereinstimmung gefunden wird, wird das Ressourcenverzeichnis auf Anwendungsebene untersucht.
  • Wenn eine Übereinstimmung immer noch nicht gefunden wird, wird ein XamlParseException ausgelöst.

Wenn der XAML-Parser daher auf eine -Erweiterung oder DynamicResource eine StaticResource Markuperweiterung stößt, sucht er nach einem übereinstimmenden Schlüssel, indem er durch die visuelle Struktur nach oben reist und die erste Übereinstimmung verwendet, die er findet. Wenn diese Suche auf der Seite endet und der Schlüssel immer noch nicht gefunden wurde, durchsucht der XAML-Parser das ResourceDictionary an das App Objekt angefügte Objekt. Wenn der Schlüssel immer noch nicht gefunden wird, wird eine Ausnahme ausgelöst.

Ressourcen außer Kraft setzen

Wenn Ressourcen Schlüssel gemeinsam nutzen, haben Ressourcen, die in der visuellen Struktur niedriger definiert sind, Vorrang vor den höher definierten Ressourcen. Wenn Sie beispielsweise eine AppBackgroundColor Ressource auf AliceBlue Anwendungsebene festlegen, wird eine Ressource auf Seitenebene AppBackgroundColor überschrieben, die auf Tealfestgelegt ist. In ähnlicher Weise wird eine Ressource auf Seitenebene AppBackgroundColor von einer Ressource auf Steuerungsebene AppBackgroundColor überschrieben.

Eigenständige Ressourcenwörterbücher

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

Um eine solche Datei zu erstellen, fügen Sie dem Projekt ein neues Inhaltsansichts - oder Inhaltsseitenelement hinzu (aber 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 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 handelt DataTemplate. MyResourceDictionary.xaml kann verwendet werden, indem sie 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 Ressourcenverzeichnisse

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

Zusammenführen lokaler Ressourcenwörterbücher

Eine lokale ResourceDictionary Datei kann in eine andere ResourceDictionary zusammengeführt werden, indem ein ResourceDictionary Objekt erstellt wird, dessen Source Eigenschaft mit den Ressourcen auf den Dateinamen der XAML-Datei festgelegt ist:

<ContentPage ...>
    <ContentPage.Resources>
        <!-- Add more resources here -->
        <ResourceDictionary Source="MyResourceDictionary.xaml" />
        <!-- Add more resources here -->
    </ContentPage.Resources>
    ...
</ContentPage>

Diese Syntax instanziieren die MyResourceDictionary -Klasse nicht. Stattdessen wird auf die XAML-Datei verwiesen. Aus diesem Grund ist beim Festlegen der Source -Eigenschaft keine CodeBehind-Datei erforderlich, und das x:Class Attribut kann aus dem Stammtag der Datei MyResourceDictionary.xaml entfernt werden.

Wichtig

Die Source Eigenschaft kann nur über XAML festgelegt werden.

Zusammenführen von Ressourcenwörterbüchern aus anderen Assemblys

Ein ResourceDictionary kann auch in eine andere ResourceDictionary zusammengeführt werden, indem sie der MergedDictionaries -Eigenschaft von ResourceDictionaryhinzugefügt wird. Mit dieser Technik können Ressourcenwörterbücher zusammengeführt werden, unabhängig von der Assembly, in der sie sich befinden. Beim Zusammenführen von Ressourcenwörterbüchern aus externen Assemblys muss ResourceDictionary eine Buildaktion auf EmbeddedResource festgelegt sein, um eine CodeBehind-Datei zu haben und das x:Class Attribut im Stammtag der Datei zu definieren.

Warnung

Die ResourceDictionary-Klasse definiert ebenfalls eine MergedWith-Eigenschaft. Diese Eigenschaft ist jedoch veraltet und sollte nicht mehr verwendet werden.

Das folgende Codebeispiel zeigt zwei Ressourcenwörterbücher, die der MergedDictionaries Auflistung einer Seitenebene ResourceDictionaryhinzugefü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 Assembly und ein Ressourcenwörterbuch aus einer externen Assembly 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 Eigenschaftselementtag in einem ResourceDictionarysein, aber Sie können so viele ResourceDictionary Objekte wie erforderlich dort einfügen.

Wenn zusammengeführte ResourceDictionary Ressourcen identische x:Key Attributwerte verwenden, Xamarin.Forms wird die folgende Ressourcenrangfolge verwendet:

  1. Die lokalen Ressourcen des Ressourcenwörterbuchs.
  2. Die Ressourcen in den Ressourcenwörterbüchern, die über die MergedDictionaries Auflistung zusammengeführt wurden, werden in umgekehrter Reihenfolge in der MergedDictionaries Eigenschaft aufgeführt.

Hinweis

Die Suche nach Ressourcenwörterbüchern kann eine rechenintensive Aufgabe sein, wenn eine Anwendung mehrere große Ressourcenwörterbücher enthält. Um unnötige Suchvorgänge 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.