ResourceDictionary- und XAML-Ressourcenreferenzen

Applies to Windows and Windows Phone

Mit XAML-Code wird die Benutzeroberfläche der App definiert, und im XAML-Code können auch Ressourcen festgelegt werden. Bei Ressourcen handelt es sich meist um Definitionen eines Objekts, das Sie voraussichtlich mehr als einmal verwenden werden. Sie geben einen Schlüssel für eine XAML-Ressource an, die für zukünftige Verweise als Name fungiert. Sie können auf eine Ressource über eine App oder von jeder darin enthaltenen XAML-Seite aus zugreifen. Windows-Runtime-XAML-Code verfügt über ein ResourceDictionary-Element, das Sie zum Definieren der Ressourcen verwenden. Anschließend können Sie auf die Ressourcen mithilfe einer StaticResource-Markuperweiterung oder ThemeResource-Markuperweiterung verweisen.

Zu den XAML-Elementen, die Sie am häufigsten als XAML-Ressourcen deklarieren werden, zählen Style, ControlTemplate, Animationskomponenten und Brush-Unterklassen. Hier werden die ResourceDictionary-Definition und die Definition von Schlüsselressourcen sowie der Bezug von XAML-Ressourcen zu anderen Ressourcen, die Sie als Teil Ihrer App oder Ihres App-Pakets definieren, erläutert. Außerdem werden die erweiterten Features des Ressourcenwörterbuchs beschrieben, z. B. MergedDictionaries und ThemeDictionaries.

Voraussetzungen

Es wird vorausgesetzt, dass Sie über Kenntnisse im Bereich XAML-Markup verfügen und die Übersicht über XAML gelesen haben.

XAML-Ressourcen müssen freigabefähig sein

Damit ein Objekt in ResourceDictionary vorhanden sein kann, muss das Objekt freigabefähig sein.

Die Freigabefähigkeit ist aus folgendem Grund erforderlich: Wenn die Objektstruktur einer App zur Laufzeit erstellt und verwendet wird, können Objekte in der Struktur nicht an mehreren Stellen gleichzeitig vorhanden sein. Das Ressourcensystem erstellt intern Kopien von Ressourcenwerten, die im Objektgraphen Ihrer App verwendet werden, wenn die einzelnen XAML-Ressourcen angefordert werden.

Ein ResourceDictionary und Windows-Runtime-XAML unterstützen die folgenden Objekte in der Regel für die freigabefähige Verwendung:

Sie können auch benutzerdefinierte Typen als freigabefähige Ressource verwenden, wenn Sie die erforderlichen Implementierungsmuster einhalten. Solche Klassen werden im zugrunde liegenden Code (oder in einbezogene Laufzeitkomponenten) definiert und dann in XAML als Ressource instantiiert. Beispiele dafür sind Objektdatenquellen und IValueConverter-Implementierungen für die Datenbindung.

Benutzerdefinierte Typen müssen einen Standardkonstruktor besitzen, da dieser von einem XAML-Parser für die Instanziierung einer Klasse verwendet wird. Benutzerdefinierte Typen, die als Ressourcen verwendet werden, können in ihrer Vererbung die UIElement-Klasse nicht besitzen, weil eine UIElement niemals freigabefähig sein kann (sie stellt immer genau ein UI-Element dar, das an einer Position im Objektgraphen Ihrer Laufzeit-App existiert).

Schlüssel für Ressourcen

Für alle Elemente in einem ResourceDictionary muss jeweils ein Schlüssel definiert sein. Ein ResourceDictionary ist aus Sicht der Programmierung tatsächlich ein Verzeichnis. Normalerweise definieren Sie Schlüssel für XAML-Ressourcen mithilfe des x:Key-Attributs. Es gibt viele verschiedene Arten von Objekten, die als XAML-Ressource verwendet werden können, und diese Objekte weisen keine gemeinsamen Windows-Runtime-Eigenschaften auf. Um es also zu ermöglichen, diesen weiten Bereich potenzieller Ressourcen in einem Ressourcenwörterbuch zu vereinen, wird das x:Key-Attribut von der XAML-Sprache global definiert. Es ist zulässig, dieses Attribut auf alle in einem Wörterbuch enthaltenen XAML-Objektelemente anzuwenden.

Der x:Key wird der Schlüssel des Verzeichniselements, und die übrigen Werte in XAML definieren ein Objekt, das den Wert des Verzeichniselements darstellt.

Für die Schlüsselnamen von Ressourcen für Windows-Runtime-XAML müssen Zeichenfolgen verwendet werden. Die Zeichenfolge muss die Regeln der XamlName-Grammatik einhalten. Lesen Sie hierzu den Abschnitt "XamlName-Grammatik" auf der Referenzseite x:Key-Attribut.

Wenn Sie in einem ResourceDictionary ein Element einfügen und das Element keinen verwendbaren Schlüssel aufweist, tritt bei der Suche nach dem Ressourcenelement durch die App ein XAML-Analysefehler auf. Wenn Sie einen Schlüssel duplizieren, tritt ein XAML-Analysefehler auf. Microsoft Visual Studio und die zugehörige XAML-Designoberfläche können oft eine Rückmeldung zur Entwurfszeit bereitstellen, wenn in Ihrem XAML Probleme mit der Ressourcendefinition oder Ressourcenreferenz vorhanden sind. Wenn der XAML-Designer jedoch keine Warnung bereitstellen kann, werden Probleme mit der XAML-Ressourcendefinition stattdessen unter Umständen als Fehler oder Ausnahmen gemeldet, wenn die App versucht, das XAML zur Laufzeit zu laden.

Implizite Schlüssel für Steuerelementvorlagen und Stile

Steuerelementvorlagen und Style-Elemente mit einer TargetType-Eigenschaft sind Spezialfälle, für deren Vorhandensein als XAML-Ressource kein x:Key-Attributwert erforderlich ist. Für diese Typen ist der Schlüssel zu der Ressource implizit. Der Wert des impliziten Schlüssels basiert auf einem Zeichenfolgenformat des in der Vorlage oder dem Stil deklarierten TargetType-Werts. Dieser Schlüssel wird zur Laufzeit von der XAML-Steuerelementlogik für die implizite Suche nach dem anzuwendenden Stil oder der anzuwendenden Vorlage verwendet. Ein Style mit TargetType="Button" kann z. B. der implizite Stil aller Button-Steuerelemente in Ihrer App sein, ohne dass ein Schlüssel für die Definition der Ressource oder eine StaticResource-Referenz von jedem Button-Element erforderlich ist. Weitere Informationen zu impliziten Stilen und ihrer Funktionsweise finden Sie unter Schnellstart: Steuerelementvorlagen.

Storyboard-Ressourcen

Eine Storyboard-Ressource stellt einen weiteren Sonderfall dar, in dem ein Storyboard ohne x:Key-Wert in einem ResourceDictionary vorhanden sein kann, sofern ein x:Name-Wert dafür angegeben ist. Das Platzieren eines Storyboard in einem ResourceDictionary dient in der Regel nicht der Wiederverwendung, da die Animationen darin bereits auf bestimmte Eigenschaften ausgerichtet sind. Ein ResourceDictionary stellt lediglich einen praktischen XAML-Container dar, in dem die verschiedenen Storyboard-Elemente platziert werden können. Letztendlich verweisen Sie nach Name auf die Storyboard-Instanzen und rufen die jeweiligen Begin-Methoden auf. Dies erfolgt in der regeln aus CodeBehind als Reaktion auf Ereignisse wie z. B. Loaded verknüpfte, von Benutzern initiierte Ereignissen. Weitere Informationen finden Sie unter Storyboardanimationen.

Direkte Ressourcen und App-Ressourcen

Es sind zwei Eigenschaften für typische Apps vorhanden. Diese enthalten die ResourceDictionary-Knoten, unter denen Sie XAML-Ressourcen definieren: FrameworkElement.Resources und Application.Resources.

FrameworkElement.Resources bietet direkte Ressourcen. Direkte Ressourcen werden mitunter auch als Seitenressourcen bezeichnet. In XAML können Sie die Technik direkter Ressourcen für den Verweis auf die XAML-Ressourcen in FrameworkElement.Resources für jedes Objekt verwenden, das mit derselben Objektstruktur verbunden ist. Damit ist im Grunde genommen dieselbe XAML-Seite gemeint, da Sie den FrameworkElement.Resources-Wert normalerweise im Stammelement einer XAML-Seite definieren, wo alle potenziellen XAML-Elemente der Seite ihn finden können.

Mit Application.Resources werden Ressourcen auf App-Ebene bereitgestellt. Die von Application.Resources definierten Ressourcen sind unabhängig davon verfügbar, welche Seite oder andere UI als aktueller Window.Content der App geladen wird. Die Angabe von Ressourcen auf App-Ebene kann hilfreich sein, wenn Sie zur Unterstützung der Navigation unterschiedliche Seiten in den Window.Content laden und vermeiden möchten, auf jeder Seite dieselben Ressourcen zu duplizieren. Wenn Sie Schlüssel-Wert-Paare (Ressourcen) einem ResourceDictionary zur Laufzeit hinzufügen, damit geladene Seiten darauf zugreifen können, stellt der App-Bereich außerdem einen Ort dar, an dem diese Ressourcen für die Lebensdauer der App beibehalten werden können.

Ein dritter Ort, an dem Ressourcen als Teil des Standardstils eines Steuerelements existieren können und der zusammen mit dem Steuerelement gepackt wird. Dieser Ort dient nur der Suche für die Ressource, die durch den DefaultStyleKey-Wert des Steuerelements als Schlüssel festgelegt wird.

Hinweis   Verwechseln Sie nicht die Konzepte bezüglich ResourceDictionary mit dem Buildvorgang für Ressourcen, mit Ressourcendateien (.resw) oder mit anderen "Ressourcen", die im Zusammenhang mit der Strukturierung des Codeprojekts erwähnt werden, mit dessen Hilfe Ihr App-Paket erzeugt wird. Weitere Informationen zu App-Ressourcenkonzepten im Allgemeinen finden Sie unter Definieren von App-Ressourcen und So wird's gemacht: Vorbereiten für die Lokalisierung.

Verweisen auf Ressourcen aus XAML

In XAML verweisen Sie von einem ResourceDictionary-Element auf eine vorhandene XAML-Ressource, indem Sie entweder die StaticResource-Markuperweiterung oder die ThemeResource-Markuperweiterung verwenden. In dieser Dokumentation werden diese als XAML-Ressourcenverweise bezeichnet. Zur Verwendung eines XAML-Ressourcenverweises mit den Markuperweiterungen verweisen Sie immer auf die Eigenschaft, die Sie mithilfe eines Attributs festlegen.

XAML-Beispielcode Zum Festlegen des Werts der Background-Eigenschaft einer Button auf die Verwendung einer statischen Ressource mit dem Namen fadeBrush müssen Sie die Ressource zunächst mit einem Schlüssel deklarieren und dann anhand des Schlüssels darauf verweisen.


<ResourceDictionary>
...
  <LinearGradientBrush x:Key="fadeBrush">
    <GradientStop Color="Red" Offset="0"/>
    <GradientStop Color="Gray" Offset="1"/>
  </LinearGradientBrush>
</ResourceDictionary>
...
 <!--XAML within a UserControl or some other root container tag that defines app UI-->
<Button Background="{StaticResource fadeBrush}" .../>


Im vorherigen Beispiel stammen die beiden XAML-Teile unter Umständen nicht einmal aus derselben XAML-Datei. Das ResourceDictionary kann in Application.Resources, in einer Designverzeichnisdatei oder in einer zusammengeführten Verzeichnisdatei definiert werden.

Sie verwenden die XAML-Attributsyntax zum Erstellen eines XAML-Ressourcenverweises. Dies ist auch dann der Fall, wenn für die von Ihnen festgelegte Eigenschaft normalerweise die Verwendung eines Eigenschaftenelements in XAML erforderlich ist. Hier sehen Sie z. B. die äquivalente Verwendung eines Eigenschaftenelements, die zeigt, dass das LinearGradientBrush-Element nicht auf eine ResourceDictionary-Ressource verweist, sondern inline definiert wird.


<Button>
  <Button.Background>
    <LinearGradientBrush>
      <GradientStop Color="Red" Offset="0"/>
      <GradientStop Color="Gray" Offset="1"/>
    </LinearGradientBrush>
  </Button.Background>
</Button>

Suchverhalten für XAML-Ressourcenverweise

Mit Suchverhalten wird bezeichnet, wie das XAML-Ressourcensystem versucht, eine XAML-Ressource zu finden. Die Suche wird für einen Schlüssel durchgeführt, der im XAML-Code der App als XAML-Ressourcenverweis referenziert wird. Das Ressourcensystem weist ein vorhersehbares Verhalten auf, was den Suchvorgang nach dem Vorhandensein einer Ressource basierend auf dem Bereich betrifft. Wenn im Anfangsbereich keine Ressource gefunden wird, wird der Bereich erweitert. Das Suchverhalten wird für alle Positionen und Bereiche beibehalten, an bzw. in denen eine XAML-Ressource durch eine App oder das System definiert sein kann. Falls keine der möglichen Ressourcensuchen erfolgreich ist, tritt häufig ein Fehler auf. In der Regel können diese Fehler während des Entwicklungsprozesses behoben werden.

Das Suchverhalten für XAML-Ressourcenverweise beginnt mit dem Objekt, bei dem die tatsächliche Verwendung angewendet wird, und mit dessen eigener Resources-Eigenschaft. Wenn dort ein ResourceDictionary vorhanden ist, wird dieses ResourceDictionary auf ein Element überprüft, das den angeforderten Schlüssel enthält. Diese erste Suchebene ist nur selten relevant, weil für dasselbe Objekt normalerweise keine Ressource definiert und anschließend referenziert wird. Vielmehr ist an dieser Stelle oft keine Resources-Eigenschaft vorhanden. Sie können XAML-Ressourcenverweise nahezu von überall in XAML erstellen; dabei sind Sie nicht auf Eigenschaften von FrameworkElement-Unterklassen beschränkt.

Anschließend überprüft die Suchsequenz das nächste übergeordnete Objekt in der Laufzeitobjektstruktur der App. Wenn eine FrameworkElement.Resources-Eigenschaft vorhanden ist und ein ResourceDictionary enthält, wird das Verzeichniselement mit der angegebenen Schlüsselzeichenfolge angefordert. Wenn die Ressource gefunden wird, hält die Suchsequenz an, und das Objekt wird an dem Ort angegeben, an dem die Referenz erstellt wurde. Andernfalls wechselt das Suchverhalten zur nächsten übergeordneten Ebene in Richtung des Objektstrukturstamms. Die Suche wird bis zum Erreichen des XAML-Stammelements rekursiv nach oben fortgesetzt, wobei die Suche an allen möglichen Orten für direkte Ressourcen erfolgt.

Hinweis  Es ist üblich, alle direkten Ressourcen auf Stammebene einer Seite zu definieren, um sowohl die Vorteile dieses Ressourcensuchverhaltens zu nutzen, als auch eine Konvention des XAML-Markupstils einzuhalten.

Wenn die angeforderte Ressource in den direkten Ressourcen nicht gefunden werden kann, besteht der nächste Schritt bei der Suche in der Überprüfung der Application.Resources-Eigenschaft. Die Application.Resources-Eigenschaft eignet sich optimal für die Positionierung von App-spezifischen Ressourcen, auf die in der Navigationsstruktur Ihrer App durch mehrere Seiten verwiesen wird.

Für Steuerelementvorlagen ist in der Referenzsuche ein weiterer möglicher Ort vorhanden: Designverzeichnisse. Bei einem Designverzeichnis handelt es sich um eine einzelne XAML-Datei mit einem ResourceDictionary-Element als Stamm. Bei einem Designverzeichnis kann es sich um ein zusammengeführtes Verzeichnis aus Application.Resources handeln. Das Designverzeichnis kann auch das steuerelementspezifische Designverzeichnis für ein benutzerdefiniertes Steuerelement mit Vorlagen sein.

Schlussendlich existiert eine Ressourcensuche für Plattformressourcen. Plattformressourcen beinhalten die Steuerelementvorlagen, die für die einzelnen Designs der System-UI definiert werden und mit deren Hilfe die Standarddarstellung aller Steuerelemente definiert wird, die Sie für die UI in einer Windows-Runtime-App verwenden. Zu den Plattformressourcen zählt auch ein Satz benannter Ressourcen im Zusammenhang mit systemweiter Darstellung und Designs. Diese Ressourcen sind aus technischer Sicht ein MergedDictionaries-Element und daher nach dem Laden der App für die XAML- oder Codesuche verfügbar. Die Systemdesignressourcen enthalten z. B. eine Ressource mit dem Namen "SystemColorWindowTextColor", die eine Color-Definition zum Abgleichen einer App-Textfarbe mit der Textfarbe eines Systemfensters bereitstellt, die vom Betriebssystem und den Benutzereinstellungen stammt. Andere XAML-Stile für Ihre App können auf diesen Stil verweisen, oder Sie können im Code einen Ressourcensuchwert abrufen (und im Beispielfall in Color umwandeln).

Weitere Informationen und eine Liste der verfügbaren designspezifischen Ressourcen sowie Systemressourcen für eine Windows Store-App, die XAML verwendet, finden Sie unter XAML-Designressourcenverweise.

Wenn der angeforderte Schlüssel an diesen Orten immer noch nicht gefunden werden kann, tritt für die XAML-Analyse ein Fehler oder eine Ausnahme auf. Unter bestimmten Umständen kann es sich bei der XAML-Analyseausnahme um eine Laufzeitausnahme handeln, die weder von einer XAML-Markupkompilierung, noch von einer XAML-Designumgebung erkannt wird.

Aufgrund des mehrstufigen Suchverhaltens für Ressourcenverzeichnisse können Sie bewusst mehrere Ressourcenelemente definieren, die jeweils denselben Zeichenfolgenwert wie der Schlüssel haben. Die einzelnen Ressourcen müssen jedoch auf unterschiedlichen Ebenen definiert sein. Anders ausgedrückt: Auch wenn die Schlüssel in einem bestimmten ResourceDictionary eindeutig sein müssen, gilt die Anforderung an die Eindeutigkeit jedoch nicht für die gesamte Sequenz des Suchverhaltens. Während der Suche wird für den XAML-Ressourcenverweis nur das erste erfolgreich abgerufene Objekt dieses Typs verwendet. Anschließend wird die Suche beendet. Sie können dieses Verhalten verwenden, um eine XAML-Ressource per Schlüssel an verschiedenen Positionen im XAML-Code Ihrer App je nach Bereich, von dem der XAML-Ressourcenverweis ausgegangen ist, und nach dem jeweiligen Verhalten der Suche anzufordern.

Zusammengeführte Ressourcenverzeichnisse

Ein zusammengeführtes Ressourcenverzeichnis ermöglicht Ihnen das Deklarieren der Inhalte eines Ressourcenverzeichnisses durch die Referenzierung einer externen Datei und die Verwendung der extern definierten Ressourcen zum Erweitern der in einer Resources-Eigenschaft gefundenen Ressourcen. Durch die Verwendung zusammengeführter Ressourcenverzeichnisse werden zwei Merkmale von Ressourcenverzeichnissen geändert: die Suchsequenz und die Anforderungen an die Eindeutigkeit des Schlüssels innerhalb eines Bereichs.

Wenn Sie ein zusammengeführtes Verzeichnis deklarieren möchten, fügen Sie einem vorhandenen MergedDictionaries-Element ein Eigenschaftenelement für die ResourceDictionary-Eigenschaft hinzu. Sie können MergedDictionaries für FrameworkElement.Resources- oder Application.Resources-Eigenschaften hinzufügen (die Zusammenführung in Application.Resources ist jedoch üblicher).

Sie müssen ResourceDictionary explizit als Objektelement deklarieren, um darin das ResourceDictionary.MergedDictionary-Eigenschaftenelement zu verwenden. Das vorhandene ResourceDictionary kann zusätzlich zu dem MergedDictionaries-Eigenschaftenelement weitere Schlüsselressourcen aufweisen. Der Inhalt eines MergedDictionaries-XAML-Eigenschaftenelements beinhaltet ein oder mehrere ResourceDictionary-Elemente, die als XAML-Objektelemente deklariert sind. Für den Inhalt von ResourceDictionary-Elementen, die zusammengeführte Verzeichnisse darstellen, sind keine zusätzlichen Schlüsselressourcen zulässig. Stattdessen dürfen diese ResourceDictionary-Elemente nur ein Attribut deklarieren: Source. Der Source-Wert gibt an, wie Sie das externe Verzeichnis des Ressourcenverzeichnisses referenzieren.

Das folgende XAML definiert beispielsweise ein ResourceDictionary mit einer Schlüsselressource sowie eine MergedDictionaries-Sammlung, die zwei unterschiedliche XAML-Ressourcenverzeichnisdateien referenziert.


<Application.Resources>
    <ResourceDictionary>
      <!--other resources can be here-->
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="rd1.xaml" />
        <ResourceDictionary Source="rd2.xaml" />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>

In MergedDictionaries können Sie mehr als ein ResourceDictionary angeben. In der Ressourcensuchsequenz wird ein MergedDictionaries-Verzeichnis nur nach erfolgter Überprüfung aller anderen Schlüsselressourcen des ResourceDictionary überprüft. Nach der Suche auf dieser Ebene werden die zusammengeführten Verzeichnisse erreicht und jedes Element in MergedDictionaries überprüft. Wenn mehrere zusammengeführte Verzeichnisse vorhanden sind, werden diese Verzeichnisse in entgegengesetzter Richtung ihrer Deklarierung in der MergedDictionaries-Eigenschaft überprüft. Wenn im vorherigen Beispiel sowohl "rd2.xaml" als auch "rd1.xaml" denselben Schlüssel deklarieren, wird zuerst der Schlüssel aus "rd2.xaml" verwendet, weil er der letzte im MergedDictionaries-Satz ist.

Innerhalb des Bereichs eines ResourceDictionary wird das Verzeichnis auf die Eindeutigkeit der Schlüssel überprüft. Dieser Bereich erstreckt sich jedoch nicht über verschiedene Elemente in MergedDictionaries-Dateien.

Sie können die Kombination aus Suchsequenz und fehlender Erzwingung eindeutiger Schlüssel für Bereiche mit zusammengeführten Verzeichnissen verwenden, um eine Fallbackwertesequenz von ResourceDictionary-Ressourcen zu erstellen. Sie können beispielsweise Benutzereinstellungen für eine bestimmte Pinselfarbe im letzten zusammengeführten Ressourcenverzeichnis in der Sequenz speichern, indem Sie ein Ressourcenverzeichnis verwenden, das mit Ihrem App-Status und den Benutzereinstellungsdaten synchronisiert wird. Wenn jedoch noch keine Benutzereinstellungen vorhanden sind, können Sie dieselbe Schlüsselzeichenfolge für eine ResourceDictionary-Ressource in der ursprünglichen MergedDictionaries-Datei definieren. Diese kann als Fallbackwert verwendet werden. Beachten Sie, dass die von Ihnen in einem primären Ressourcenverzeichnis bereitgestellten Werte immer geprüft werden, bevor eine Überprüfung der zusammengeführten Verzeichnisse erfolgt. Wenn Sie die Fallbacktechnik verwenden möchten, definieren Sie daher die Ressource nicht in einem primären Ressourcenverzeichnis.

Designverzeichnisse

Bei einem Designverzeichnis handelt es sich um einen speziellen Typ zusammengeführter Verzeichnisse für die Speicherung der Ressourcen, die in Abhängigkeit davon variieren, welches Design ein Benutzer momentan auf seinem PC verwendet. Beispielsweise kann für das Design "Hell" ein Pinsel mit weißer Farbe verwendet werden, während für das Standarddesign ein Pinsel mit dunkler Farbe verwendet wird. Der Pinsel ändert die Ressource, in der er aufgelöst wird, aber die Komposition eines Steuerelements, für das der Pinsel als Ressource verwendet wird, kann identisch sein. Nur die Designressource ändert sich. Um das Designwechselverhalten in Ihren eigenen Vorlagen und Stilen zu reproduzieren, müssen Sie, anstatt diese Elemente mit MergedDictionaries als Eigenschaft in den Hauptverzeichnissen zusammenzuführen, die ThemeDictionaries-Eigenschaft verwenden. Genau wie bei MergedDictionaries legen Sie diese Eigenschaft mithilfe der Syntax für Eigenschaftenelemente fest, und der Wert der Eigenschaft entspricht einem oder mehreren ResourceDictionary-Objektelementen.

Dabei muss jedes ResourceDictionary-Element in ThemeDictionaries über einen x:Key-Wert verfügen. Dieser Wert ist eine Zeichenfolge, mit deren Hilfe das relevante Design benannt wird, beispielsweise "Default", "Light" oder "HighContrast".

Für die enthaltenen ResourceDictionary-Elemente kann eins von zwei möglichen Modellen verwendet werden:

  • Das ResourceDictionary hat nur ein Attribut (Source) und keine weiteren Inhalte. Die Source bezieht sich auf eine separate XAML-Datei, die nur einen ResourceDictionary-Stamm enthält. Von diesem Verzeichnis werden anschließend spezielle Schlüsselelemente für das Design definiert, das durch den x:Key-Wert im ResourceDictionary-Element zur Angabe der Source benannt wird. Der Source-Wert referenziert normalerweise eine XAML-Datei in Ihrer Projektstruktur und Ihrem App-Paket.
  • Das ResourceDictionary enthält spezielle Schlüsselelemente für das jeweilige Design, das durch den x:Key-Wert im übergeordneten ResourceDictionary-Element benannt wird.

Zudem kann ein Schlüssel ähnlich wie bei zusammengeführten Verzeichnissen mehrmals in einem Satz von Designverzeichnissen in derselben ThemeDictionaries-Sammlung definiert werden, sofern die Eindeutigkeit in den einzelnen ResourceDictionary-Einheiten gegeben ist. Dies entspricht in der Tat dem gewünschten Konzept: Für jedes Designverzeichnis sollte ein identischer Schlüsselsatz vorhanden sein. Andernfalls verursacht wahrscheinlich jedes Design, in dem einer der Schlüssel fehlt, ein UI-Problem beim Laden des jeweiligen Designs. Im Gegensatz zu zusammengeführten Verzeichnissen spielt die Definitionsreihenfolge der einzelnen Designs keine Rolle. Bei Designverzeichnissen ändert sich das für die Ressourcensuche zu verwendende aktive Verzeichnis dynamisch, wenn mit einer ThemeResource-Markuperweiterung ein Verweis erstellt wird und das System eine Designänderung erkennt. Das Suchverhalten des Systems basiert auf der Zuordnung des aktiven Designs zum x:Key-Element eines speziellen Designverzeichnisses.

Eine Untersuchung der Strukturierung der Designverzeichnisse in den XAML-Standarddesignressourcen kann sehr hilfreich sein. Die XAML-Standarddesignressourcen entsprechen den Vorlagen, die die Windows-Runtime standardmäßig für ihre Steuerelemente verwendet. Öffnen Sie die XAML-Dateien in \(Program Files)\Windows Kits\<version>\Include\winrt\xaml\design mit einem Text- oder vergleichbaren Editor in Ihrer IDE. Beachten Sie, wie die Designverzeichnisse zunächst in generic.xaml definiert sind und wie dieselben Schlüssel von den einzelnen Designverzeichnissen definiert werden. Alle diese Schlüssel werden anschließend von Kompositionselementen in den verschiedenen Schlüsselelementen referenziert, die sich außerhalb der Designverzeichnisse befinden und später im XAML definiert werden. Außerdem gibt es eine separate Datei themeresources.xaml für Designs, die nur die Designressourcen und zusätzlichen Vorlagen enthält, aber nicht die standardmäßigen Steuerelementvorlagen. Die Designbereiche sind Duplikate der Bereiche in generic.xaml.

Wenn Sie Kopien von Stilen oder Vorlagen mit XAML-Designtools bearbeiten, extrahieren die Designtools Abschnitte der XAML-Designressourcenverzeichnisse und platzieren diese als lokale Kopien von XAML-Verzeichniselementen, die Teil Ihrer App und Ihres Projekts sind.

Weitere Informationen und eine Liste der verfügbaren designspezifischen Ressourcen sowie Systemressourcen für eine Windows Store-App, die XAML verwendet, finden Sie unter XAML-Designressourcenverweise.

Windows 8-Verhalten

Unter Windows 8 wurde die ThemeResource-Markuperweiterung nicht unterstützt. Sie ist ab Windows 8.1 verfügbar. Außerdem wurde unter Windows 8 auch das dynamische Umschalten zwischen den designbezogenen Ressourcen für eine Windows-Runtime-App nicht unterstützt. Die App musste neu gestartet werden, damit die Designänderung für die XAML-Vorlagen und -Formate wirksam wurde. Dieses Verhalten beeinträchtigt die Benutzerfreundlichkeit. Es wird daher dringend empfohlen, Apps neu zu kompilieren und auf Windows 8.1 auszurichten, damit Formate mit Nutzung von ThemeResource verwendet werden können und dynamisch zwischen Designs gewechselt werden kann, wenn Benutzer dies wünschen. Apps, die für Windows 8 kompiliert wurden, aber unter Windows 8.1 ausgeführt werden, weisen weiterhin das Windows 8-Verhalten auf.

Vorreferenzen in einem ResourceDictionary

XAML-Ressourcenverweise in einem bestimmten Ressourcenverzeichnis müssen auf eine Ressource verweisen, die bereits mit einem Schlüssel definiert wurde. Diese Ressource muss lexikalisch vor dem Ressourcenverweis angezeigt werden. Vorwärtsverweise können nicht durch einen XAML-Ressourcenverweis aufgelöst werden. Aus diesem Grund müssen Sie bei Verwendung von XAML-Ressourcenverweisen in einer anderen Ressource die Ressourcenverzeichnisstruktur so konzipieren, dass die von anderen Ressourcen verwendeten Ressourcen in einem Ressourcenverzeichnis zuerst definiert werden.

Auf App-Ebene definierte Ressourcen können nicht auf direkte Ressourcen verweisen. Dies ist gleichbedeutend mit einer Vorreferenz, da die App-Ressourcen tatsächlich zuerst verarbeitet werden (wenn die App zuerst gestartet wird, noch vor dem Laden von Navigationsseiteninhalten). Direkte Ressourcen können jedoch auf eine App-Ressource verweisen. Diese Tatsache kann eine hilfreiche Technik zum Vermeiden von Situationen mit Vorreferenzen sein.

UserControl-Verwendungsbereich

Ein UserControl-Element umfasst eine spezielle Situation für das Ressourcensuchverhalten, da es die vererbten Konzepte eines Definitions- und Verwendungsbereichs enthält. Ein UserControl-Element mit einem XAML-Ressourcenverweis aus dem zugehörigen Definitionsbereich muss die Suche der jeweiligen Ressource innerhalb der eigenen Suchsequenz für den Definitionsbereich unterstützen können. Das heißt, es kann nicht auf App-Ressourcen zugreifen. In einem UserControl-Verwendungsbereich wird ein Ressourcenverweis so behandelt, als würde er sich innerhalb der Suchsequenz in Richtung des zugehörigen Seitenstamms befinden (wie eine andere Ressourcenreferenz, die von einem Objekt in einer geladenen Objektstruktur erstellt wird) und als könnte sie auf App-Ressourcen zugreifen.

ResourceDictionary und XamlReader.Load

Sie können ein ResourceDictionary als Stamm oder als Teil der XAML-Eingabe für die XamlReader.Load-Methode verwenden. Sie können in diesen XAML-Code auch XAML-Ressourcenverweise einfügen, wenn all diese Referenzen im XAML-Code, der zum Laden übermittelt wird, vollständig eigenständig sind. XamlReader.Load analysiert den XAML-Code in einem Kontext , in dem keine anderen ResourceDictionary-Objekte beachtet werden, nicht einmal Application.Resources. Außerdem sollten Sie {ThemeResource} nicht in XAML-Code verwenden, der an XamlReader.Load übermittelt wird.

Verwenden eines ResourceDictionary aus Code

Die meisten Szenarien für ein ResourceDictionary werden ausschließlich im XAML-Code behandelt. Sie deklarieren den ResourceDictionary-Container und die darin enthaltenen Ressourcen als XAML-Datei oder Gruppe von XAML-Knoten in einer UI-Definitionsdatei. Anschließend nutzen Sie XAML-Ressourcenverweise, um diese Ressourcen aus anderen Teilen des XAML-Codes anzufordern. Es gibt trotzdem noch bestimmte Fälle, in denen die App den Inhalt eines ResourceDictionary-Elements mithilfe von Code anpassen sollte, der bei laufender App ausgeführt wird, oder in denen wenigstens der Inhalt eines ResourceDictionary-Elements daraufhin abgefragt werden sollte, ob eine Ressource bereits definiert ist. Diese Codeaufrufe werden für eine ResourceDictionary-Instanz erstellt. Daher müssen Sie eine Instanz abrufen, und zwar entweder ein direktes ResourceDictionary in der Objektstruktur durch Abrufen von FrameworkElement.Resources oder Application.Current.Resources.

In C#- oder Microsoft Visual Basic-Code können Sie in einem bestimmten ResourceDictionary mithilfe des Indexers (Item) auf eine Ressource verweisen. Bei einem ResourceDictionary handelt es sich um ein Verzeichnis mit Zeichenfolgenschlüsseln, sodass vom Indexer anstelle eines Ganzzahlindex der Zeichenfolgenschlüssel verwendet wird. Für Visual C++-Komponentenerweiterungscode (C++/CX) verwenden Sie Lookup.

Bei der Verwendung von Code zum Untersuchen oder Ändern eines ResourceDictionary-Elements, wechselt das Verhalten für APIs wie z. B. Lookup oder Item nicht von direkten Ressourcen zu App-Ressourcen. Dies ist das Verhalten eines Parsers, das nur beim Laden von XAML-Seiten auftritt. Zur Laufzeit gilt der Bereich für Schlüssel eigenständig für die ResourceDictionary-Instanz, die Sie gerade verwenden. Der Bereich wird jedoch auf MergedDictionaries erweitert.

Wenn Sie zudem einen Schlüssel anfordern, der im ResourceDictionary nicht vorhanden ist, tritt ggf. kein Fehler auf. Für den Rückgabewert kann einfach null angegeben werden. Unter Umständen erhalten Sie dennoch einen Fehler, wenn Sie versuchen, das zurückgebende Ergebnis null als Wert zu verwenden. Der Fehler würde durch den Setter für die Eigenschaft ausgelöst, nicht durch Ihren ResourceDictionary-Aufruf. Ein Fehler kann nur dann vermieden werden, wenn die Eigenschaft null als gültigen Wert akzeptiert. Beachten Sie, wie sich dieses Verhalten vom XAML-Suchverhalten zur XAML-Analysezeit unterscheidet. Wenn der bereitgestellte Schlüssel aus dem XAML-Code zur Analysezeit nicht aufgelöst werden kann, tritt auch dann ein XAML-Analysefehler auf, wenn null von der Eigenschaft akzeptiert worden wäre.

Zusammengeführte Ressourcenverzeichnisse werden in den Indexbereich des primären Ressourcenverzeichnisses einbezogen, das zur Laufzeit auf das zusammengeführte Verzeichnis verweist. Das heißt, dass Sie Item oder Lookup des primären Verzeichnisses zum Suchen von Objekten verwenden können, die tatsächlich im zusammengeführten Verzeichnis definiert wurden. In diesem Fall ähnelt das Suchverhalten dem XAML-Suchverhalten zur Analysezeit: Wenn zusammengeführte Verzeichnisse mit demselben Schlüssel mehrere Objekte enthalten, wird das Objekt des zuletzt hinzugefügten Verzeichnisses zurückgegeben.

Sie dürfen einem vorhandenen ResourceDictionary Elemente hinzufügen, indem Sie Add (C# oder Visual Basic) oder Insert (C++/CX) aufrufen. Hinzufügungen sind dabei sowohl für direkte Ressourcen als auch für App-Ressourcen möglich. Für all diese API-Aufrufe ist ein Schlüssel erforderlich, der die Anforderung erfüllt, dass jedes Element in einem ResourceDictionary über einen Schlüssel verfügt. Elemente, die Sie einem ResourceDictionary zur Laufzeit hinzufügen, sind für XAML-Ressourcenverweise nicht relevant. Die erforderliche Suche nach XAML-Ressourcenverweisen wird durchgeführt, wenn der XAML-Code beim Laden der App (oder bei Ermittlung einer Designänderung) zum ersten Mal analysiert wird. Ressourcen, die Sammlungen zur Laufzeit hinzugefügt wurden, waren zu diesem Zeitpunkt noch nicht verfügbar. Eine Änderung des ResourceDictionary-Elements führt nicht dazu, dass eine daraus bereits abgerufene Ressource auch dann nicht ungültig wird, wenn Sie den Wert dieser Ressource ändern.

Sie haben auch die Möglichkeit, zur Laufzeit Elemente aus einem ResourceDictionary zu entfernen, Kopien von einigen oder allen Elementen zu erstellen und andere Vorgänge auszuführen. Die Elementliste für ResourceDictionary gibt an, welche APIs verfügbar sind. Da das ResourceDictionary eine projizierte API zur Unterstützung der zugrunde liegenden Auflistungsschnittstelle aufweist, gilt es zu beachten, dass Ihre API-Optionen je nach Verwendung von C# oder Visual Basic anstelle von C++/CX variieren.

ResourceDictionary und Lokalisierung

Ein XAML-ResourceDictionary enthält anfangs unter Umständen Zeichenfolgen, die lokalisiert werden müssen. Wenn dies der Fall ist, speichern Sie diese Zeichenfolgen nicht in einem ResourceDictionary, sondern als Projektressourcen. Entfernen Sie die Zeichenfolgen aus dem XAML, und weisen Sie dem besitzenden Element einen x:Uid-Wert zu. Definieren Sie anschließend eine Ressource in einer Ressourcendatei. Geben Sie einen Ressourcennamen im Format XUIDValue.PropertyName und einen Ressourcenwert der zu lokalisierenden Zeichenfolge an. Weitere Informationen finden Sie unter Schnellstart: Übersetzen von UI-Ressourcen.

Optimierung des Ladens von Ressourcen in Windows 8.1

Ab Windows 8.1 wird eine Optimierung des Ladens von Ressourcen eingeführt, die durch das App-Modell und den Windows-Runtime-XAML-Parser ermöglicht wird. In Windows 8 hat der XAML-Parser Ressourcen aus app.xaml geladen und jeweils als Objekte des Startvorgangs erstellt. Dies war für große Verzeichnisse nicht sehr effizient. Zudem waren die in den Ressourcen enthaltenen Elemente für drei Designs definiert, wobei nur das aktuelle Design wirklich erforderlich ist. Ab Windows 8.1 erstellt der XAML-Parser die Ressourcen nur, wenn sie explizit von XAML-Ressourcenverweisen angefordert werden. Diese könne aus anderen Ressourcen oder aus der XAML auf Seitenebene beim Laden der jeweiligen Seite stammen. Das optimierte XAML-Parserverhalten minimiert die für das Lesen des Verzeichnisses auf App-Ebene beim Startvorgang erforderliche Zeit und sorgt in den meisten Fällen dafür, dass die erste App-Seite schneller geladen wird. Ressourcen, die für inaktive Designs erforderlich sind, werden nur geladen, wenn das Design vom Benutzer aktiviert wird. Benutzer wechseln in der Regel nicht zwischen Designs, während eine App ausgeführt wird. Sollte dies dennoch erfolgen, werden alle Ressourcen, für die die ThemeResource-Markuperweiterung für die Anforderung verwendet wurde, basierend auf dem neuen aktiven Design neu berechnet.

Windows 8-Verhalten

Unter Windows 8 waren die oben beschriebenen Optimierungen nicht verfügbar. Aus diesem Grund kann es zu Abweichungen beim Timing kommen, wenn Sie die App für Windows 8.1 neu zuweisen. Die App sollte dann schneller geladen werden. Es kann jedoch sein, dass diese Verbesserung aufgrund der anderen Änderungen, die Sie im Rahmen der Neuzuweisung am App-Code vorgenommen haben, nicht einzeln als solche erkennbar ist. Einige Bereiche, in denen Sie ggf. Veränderungen beim Timing aufgrund des optimierten Ressourcenladevorgangs beobachten können, sind das Aufrufen der Konstruktoren durch den Parser, für Objekte wie Application, Konverter oder andere benutzerdefinierte Klassen. Apps, die für Windows 8 kompiliert wurden, aber unter Windows 8.1 ausgeführt werden, weisen weiterhin das Windows 8-Verhalten auf.

Benutzerdefinierte Ressourcensuche

Für erweiterte Szenarien können Sie eine Klasse implementieren, die von dem hier beschriebenen Suchverhalten für XAML-Ressourcenverweise abweicht. Implementieren Sie dazu die CustomXamlResourceLoader-Klasse. Sie können dann mithilfe der CustomResource-Markuperweiterung statt über StaticResource oder ThemeResource auf dieses Verhalten zugreifen. Die meisten Apps verfügen nicht über Szenarien, für die dies erforderlich ist. Weitere Informationen finden Sie unter CustomXamlResourceLoader.

Verwandte Themen

ResourceDictionary
Übersicht über XAML
StaticResource-Markuperweiterung
ThemeResource-Markuperweiterung
XAML-Designressourcenverweise
Schnellstart: Übersetzen von UI-Ressourcen
Schnellstart: Formatieren von Steuerelementen
Anwendungsressourcen und Lokalisierung – Beispiel
x:Key-Attribut

 

 

Anzeigen:
© 2014 Microsoft