XAML-Designressourcen

Designressourcen in XAML sind Ressourcen, die abhängig vom aktiven Systemdesign verschiedene Werte anwenden. Es gibt drei Designs, die vom XAML-Framework unterstützt werden: „Light“, „Dark“ und „HighContrast“.

Voraussetzungen: In diesem Thema wird vorausgesetzt, dass Sie ResourceDictionary- und XAML-Ressourcenreferenzen gelesen haben.

Designressourcen im Vergleich zu statischen Ressourcen

Es gibt zwei XAML-Markuperweiterungen, die aus einem vorhandenen XAML-Ressourcenverzeichnis auf eine XAML-Ressource verweisen können: die {StaticResource}-Markuperweiterung und die {ThemeResource}-Markuperweiterung.

Die Auswertung einer {ThemeResource}-Markuperweiterung tritt beim Laden der App und anschließend bei jeder Änderung des Designs zur Laufzeit auf. Dies ist in der Regel das Ergebnis einer Änderung von Geräteeinstellungen durch Benutzer*innen oder einer programmgesteuerten Änderung in der App, die das aktuelle Design ändert.

Für eine {StaticResource}-Markuperweiterung erfolgt eine Auswertung hingegen nur, wenn der XAML-Code das erste Mal von der App geladen wird. Es findet keine Aktualisierung statt. Dies ähnelt dem Suchen und Ersetzen in XAML-Code mit dem tatsächlichen Laufzeitwert beim Start der App.

Designressourcen in der Ressourcenverzeichnisstruktur

Jede Designressource ist Teil der XAML-Datei „themeresources.xaml“. Zu Designzwecken steht „themeresources.xaml“ im Ordner „\(Programme)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK-Version>\Generic“ einer Installation des Windows Software Development Kit (SDK) zur Verfügung. Die Ressourcenverzeichnisse in „themeresources.xaml“ werden auch in „generic.xaml“ im selben Verzeichnis reproduziert.

Die Windows-Runtime verwendet diese physischen Dateien nicht für die Runtime-Suche. Daher befinden sie sich in einem speziellen DesignTime-Ordner und werden nicht standardmäßig in Apps kopiert. Stattdessen sind die Ressourcenverzeichnisse als Teil der Windows-Runtime selbst im Speicher vorhanden, und die XAML-Ressource Ihrer App verweist auf Designressourcen (oder Systemressourcen), die dort zu Laufzeit aufgelöst werden.

Richtlinien für benutzerdefinierte Designressourcen

Halten Sie sich an die folgenden Richtlinien, wenn Sie Ihre eigenen benutzerdefinierten Designressourcen definieren und verwenden:

  • Geben Sie zusätzlich zum Verzeichnis „HighContrast“ jeweils Designverzeichnisse für „Light“ und „Dark“ an. Sie können zwar ein ResourceDictionary mit „Default“ als Schlüssel erstellen, es empfiehlt sich jedoch, explizit vorzugehen und stattdessen „Light“, „Dark“ und „HighContrast“ zu verwenden.

  • Verwenden Sie die {ThemeResource}-Markuperweiterung in Formatvorlagen, Settern, Steuerelementvorlagen, Eigenschaftensätzen und Animationen.

  • Verwenden Sie die {ThemeResource}-Markuperweiterung nicht in Ihren Ressourcendefinitionen in ThemeDictionaries. Verwenden Sie stattdessen die {StaticResource}-Markuperweiterung.

    AUSNAHME: Sie können die {ThemeResource}-Markuperweiterung verwenden, um auf Ressourcen zu verweisen, die keinen Bezug zum App-Design in ThemeDictionaries haben. Beispiele für diese Ressourcen sind Akzentfarbenressourcen wie SystemAccentColor oder Systemfarbenressourcen, die normalerweise das Präfix „SystemColor“ haben, z. B. SystemColorButtonFaceColor.

Achtung

Wenn Sie diesen Richtlinien nicht folgen, kann ein unerwartetes Verhalten im Zusammenhang mit Designs in Ihrer App auftreten. Weitere Informationen finden Sie im Abschnitt Problembehandlung bei Designressourcen.

Die XAML-Farbskala und designabhängige Pinsel

Die kombinierte Farbpalette für die Designs „Light“, „Dark“ und „HighContrast“ bilden die Windows-Farbskala in XAML. Egal, ob Sie die Systemdesigns ändern oder ein Design auf Ihre eigenen XAML-Elemente anwenden möchten, ist es wichtig zu verstehen, wie die Farbressourcen strukturiert werden.

Weitere Informationen zur Anwendung von Farbe in Windows-Apps finden Sie unter Farbe in Windows-Apps.

Farben im hellen und dunklen Design

Das XAML-Framework stellt eine Gruppe von benannten Color-Ressourcen mit Werten bereit, die speziell auf die Designs „Light“ und „Dark“ zugeschnitten sind. Für WinUI 2 werden die Designressourcen in der XAML-Datei mit den allgemeinen Designressourcen definiert. Die Farbnamen sind sehr beschreibend und weisen auf die beabsichtigte Verwendung hin. Es gibt jeweils eine SolidColorBrush-Ressource für jede Color-Ressource.

Tipp

Eine visuelle Übersicht über diese Farben finden Sie in der WinUI 3 Gallery-App: Farben

Die WinUI 3-Katalog-App umfasst interaktive Beispiele für die meisten WinUI 3-Steuerelemente, -Features und -Funktionen. Laden Sie die App aus dem Microsoft Store herunter, oder rufen Sie den Quellcode auf GitHub ab

Windows-Systemfarben im Design mit hohem Kontrast

Zusätzlich zu den Ressourcen, die vom XAML-Framework bereitgestellt werden, gibt es eine Reihe von Farbwerten, die von der Windows-Systempalette abgeleitet werden. Diese Farben werden nicht speziell für die Windows-Runtime- oder Windows-Apps verwendet. Viele der XAML-Brush-Ressourcen verwenden diese Farben jedoch, wenn das System mit dem Design „HighContrast“ betrieben wird (und die App ausgeführt wird). Das XAML-Framework stellt diese systemweiten Farben als Ressourcen mit Schlüssel bereit. Die Schlüssel folgen diesem Benennungsformat: SystemColor[name]Color.

Weitere Informationen zum Unterstützen von Designs mit hohem Kontrast finden Sie unter Designs mit hohem Kontrast.

Systemakzentfarbe

Neben der Systemdesignfarben mit hohem Kontrast wird die Akzentfarbe des Systems als spezielle Ressource mit dem Schlüssel SystemAccentColor bereitgestellt. Zur Laufzeit ruft diese Ressource die Farbe ab, die von den Benutzer*innen als Akzentfarbe in den Windows-Einstellungen zur Personalisierung angegeben wurde.

Hinweis

Die Systemfarbenressourcen können zwar überschrieben werden, es empfiehlt sich jedoch, die Farbauswahl der Benutzer*innen zu respektieren, dies gilt insbesondere für Einstellungen für hohen Kontrast.

Designabhängige Pinsel

Die in den vorherigen Abschnitten gezeigten Farbressourcen dienen zum Festlegen der Color-Eigenschaft von SolidColorBrush-Ressourcen in den Systemdesign-Ressourcenwörterbüchern. Sie verwenden die Pinselressourcen, um Farben auf XAML-Elemente anzuwenden.

Im Folgenden erfahren Sie, wie der Farbwert für diesen Pinsel zur Laufzeit bestimmt wird. In den Ressourcenverzeichnissen „Light“ und „Dark“ wird dieser Pinsel wie folgt definiert:

<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{StaticResource TextFillColorPrimary}"/>

Im Ressourcenverzeichnis „HighContrast“ wird dieser Pinsel wie folgt definiert:

<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{ThemeResource SystemColorWindowTextColor}"/>

Bei der Anwendung dieses Pinsels auf ein XAML-Element wird die Farbe zur Laufzeit durch das aktuelle Design bestimmt, wie in dieser Tabelle zu sehen ist.

Design Farbressourcen Laufzeitwert
Hell TextFillColorPrimary #E4000000
Dunkel TextFillColorPrimary #FFFFFFFF
HighContrast SystemColorWindowTextColor Die in den Einstellungen für Text angegebene Farbe.

Die XAML-Typskala

Die Datei „themeresources.xaml“ definiert verschiedene Ressourcen, die eine Formatvorlage definieren, die Sie auf Textcontainer in Ihrer UI speziell für TextBlock oder RichTextBlock anwenden können. Dies sind nicht die impliziten Standardformatvorlagen. Sie werden bereitgestellt, um Ihnen das Erstellen von XAML-Benutzeroberflächendefinitionen zu vereinfachen, die der in Richtlinien für Schriftarten dokumentierten Windows-Typskala entsprechen.

Diese Formatvorlagen sind für Textattribute gedacht, die Sie auf den gesamten Textcontainer anwenden möchten. Wenn Sie Formatvorlagen nur auf Textabschnitte anwenden möchten, legen Sie Attribute für die Textelemente im Container fest, zum Beispiel für Run in TextBlock.Inlines oder für einen Absatz in RichTextBlock.Blocks.

Die Formatvorlagen sehen bei Anwendung auf einen TextBlock wie folgt aus:

text block styles

Stil Weight Size
Caption Regulär 12
Body Regulär 14
Body Strong Halbfett 14
Body Large Regulär 18
Untertitel Halbfett 20
Titel Halbfett 28
Title Large Halbfett 40
Anzeigen Halbfett 68
<TextBlock Text="Caption" Style="{StaticResource CaptionTextBlockStyle}"/>
<TextBlock Text="Body" Style="{StaticResource BodyTextBlockStyle}"/>
<TextBlock Text="Body Strong" Style="{StaticResource BodyStrongTextBlockStyle}"/>
<TextBlock Text="Body Large" Style="{StaticResource BodyLargeTextBlockStyle}"/>
<TextBlock Text="Subtitle" Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Title" Style="{StaticResource TitleTextBlockStyle}"/>
<TextBlock Text="Title Large" Style="{StaticResource TitleLargeTextBlockStyle}"/>
<TextBlock Text="Display" Style="{StaticResource DisplayTextBlockStyle}"/>

Eine Anleitung zur Verwendung der Windows-Typhierarchie in Ihrer App finden Sie unter Typografie in Windows-Apps.

Details zu den XAML-Formatvorlagen finden Sie unter WinUI auf GitHub:

Tipp

Eine visuelle Übersicht über diese Formatvorlagen finden Sie in der WinUI 3 Gallery-App: Typografie

BaseRichTextBlockStyle

TargetType:RichTextBlock

Stellt die gemeinsamen Eigenschaften für alle anderen RichTextBlock-Containerformatvorlagen bereit.

<!-- Usage -->
<RichTextBlock Style="{StaticResource BaseRichTextBlockStyle}">
    <Paragraph>Rich text.</Paragraph>
</RichTextBlock>

<!-- Style definition -->
<Style x:Key="BaseRichTextBlockStyle" TargetType="RichTextBlock">
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontWeight" Value="SemiBold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="TextTrimming" Value="None"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="LineStackingStrategy" Value="MaxHeight"/>
    <Setter Property="TextLineBounds" Value="Full"/>
    <Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

BodyRichTextBlockStyle

<!-- Usage -->
<RichTextBlock Style="{StaticResource BodyRichTextBlockStyle}">
    <Paragraph>Rich text.</Paragraph>
</RichTextBlock>

<!-- Style definition -->
<Style x:Key="BodyRichTextBlockStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaseRichTextBlockStyle}">
    <Setter Property="FontWeight" Value="Normal"/>
</Style>

Hinweis: Die RichTextBlock-Formatvorlagen verfügen nicht über alle Textskala-Formatvorlagen von TextBlock. Dies liegt hauptsächlich daran, dass das blockbasierte Dokumentobjektmodell für RichTextBlock das Festlegen von Attributen für die einzelnen Textelemente vereinfacht. Außerdem entsteht, wenn Sie TextBlock.Text mit der XAML-Inhaltseigenschaft festlegen, eine Situation, in der kein zu formatierendes Textelement vorhanden ist und Sie daher den Container formatieren müssen. Das ist für RichTextBlock kein Problem, da sein Textinhalt immer in spezifischen Textelementen wie Absatz enthalten sein muss, in denen Sie XAML-Stile für die Kopfzeile, die Seitenunterüberschrift und ähnliche Texthierarchiedefinitionen festlegen können.

Sonstige benannte Formatvorlagen

Es gibt eine Reihe von weiteren Formatvorlagen-Definitionen mit Schlüsseln, die Sie auf ein Schaltflächen-Element anders als dessen implizite Standardformatvorlage anwenden können.

TargetType:Button

Diese Formatvorlage stellt eine vollständige Vorlage für ein Schaltflächen-Element bereit, bei der es sich um die Navigationsschaltfläche „Zurück“ für eine Navigations-App handeln kann. Die Standardgröße ist 40 × 40 Pixel. Um die Formatvorlage anzupassen, können Sie die Eigenschaften Height, Width, FontSize und andere für Ihr Schaltflächen-Element explizit festlegen oder eine abgeleitete Formatvorlage mithilfe von BasedOn erstellen.

Hier ist ein Schaltflächen-Element mit der angewendeten NavigationBackButtonNormalStyle-Ressource.

<Button Style="{StaticResource NavigationBackButtonNormalStyle}" />

Dies sieht wie folgt aus:

A button styled as a back button

TargetType:Button

Diese Formatvorlage stellt eine vollständige Vorlage für ein Schaltflächen-Element bereit, bei der es sich um die Navigationsschaltfläche „Zurück“ für eine Navigations-App handeln kann. Sie ähnelt NavigationBackButtonNormalStyle, aber die Größe beträgt 30x30 Pixel.

Hier sehen Sie eine Schaltfläche mit darauf angewendeter NavigationBackButtonSmallStyle-Ressource.

<Button Style="{StaticResource NavigationBackButtonSmallStyle}" />

Problembehandlung bei Designressourcen

Wenn Sie den Richtlinien für die Verwendung von Designressourcen nicht folgen, kann unerwartetes Verhalten im Zusammenhang mit Designs in Ihrer App auftreten.

Wenn Sie beispielsweise ein Flyout mit hellem Design öffnen, ändern sich auch Teile der App mit dem dunklen Design so, als wären sie im hellen Design. Wenn Sie zu einer Seite mit hellem Design und dann zurück navigieren, sieht die ursprüngliche Seite mit dunklem Design (oder Teile davon) so aus, als wäre sie im hellen Design.

Diese Arten von Problemen treten in der Regel auf, wenn Sie ein Standard-Design und ein HighContrast-Design für die Unterstützung von Szenarien mit hohem Kontrast bereitstellen und dann Light- und Dark-Designs in verschiedenen Teilen der App verwenden.

Betrachten Sie beispielsweise diese Definition eines Designverzeichnisses:

<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Intuitiv sieht sie richtig aus. Sie möchten die Farbe ändern, auf die durch myBrush mit hohem Kontrast verwiesen wird. Außerhalb des hohen Kontrasts vertrauen Sie aber auf die {ThemeResource}-Markuperweiterung, um sicherzustellen, dass myBrush auf die richtige Farbe für das Design verweist. Wenn Ihre App nie FrameworkElement.RequestedTheme für Elemente in der visuellen Struktur festgelegt hat, funktioniert dies in der Regel wie erwartet. Allerdings treten Probleme in Ihrer App auf, sobald Sie das Design verschiedener Teile der visuellen Struktur ändern.

Das Problem tritt auf, da Pinsel im Gegensatz zu den meisten anderen XAML-Typen gemeinsam genutzte Ressourcen sind. Wenn Sie zwei Elemente in XAML-Unterstrukturen mit verschiedenen Designs haben, die auf dieselbe Pinselressource verweisen, und das Framework für jede Teilstruktur eine Aktualisierung der Ausdrücke der {ThemeResource}-Markuperweiterung durchführt, werden Änderungen an der freigegebenen Pinselressource in der anderen untergeordneten Struktur wiedergegeben, was nicht dem gewünschten Ergebnis entspricht.

Ersetzen Sie zum Beheben dieses Problems das Verzeichnis „Default“ durch separate Designverzeichnisse für die Designs „Light“ und „Dark“ zusätzlich zu „HighContrast“:

<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Allerdings treten weiterhin Probleme auf, wenn auf eine dieser Ressourcen in geerbten Eigenschaften wie Foreground verwiesen wird. Die benutzerdefinierte Steuerelementvorlage gibt möglicherweise die Vordergrundfarbe für ein Element mit der {ThemeResource}-Markuperweiterung an, aber wenn das Framework den geerbten Wert an die untergeordneten Elemente weitergibt, stellt es einen direkten Verweis auf die Ressource bereit, die durch den Ausdruck der {ThemeResource}-Markuperweiterung aufgelöst wurde. Dies führt zu Problemen, wenn das Framework Designänderungen verarbeitet, während es die visuelle Struktur des Steuerelements durchläuft. Es wertet den Ausdruck der {ThemeResource}-Markuperweiterung neu aus, um eine neue Pinselressource abzurufen, gibt diesen Verweis aber noch nicht an die untergeordneten Elemente des Steuerelements weiter. Dies geschieht später, zum Beispiel beim nächsten Messwertdurchlauf.

Nach dem Durchlaufen der visuellen Struktur des Steuerelements in Reaktion auf eine Designänderung durchläuft das Framework daher die untergeordneten Elemente und aktualisiert Ausdrücke der {ThemeResource}-Markuperweiterung für sie oder für Objekte, die für ihre Eigenschaften festgelegt sind. Hier tritt das Problem auf. Das Framework durchläuft die Pinselressource, und da die Farbe mit einer {ThemeResource}-Markuperweiterung angegeben wird, erfolgt eine erneute Auswertung.

An dieser Stelle hat das Framework Ihr Designverzeichnis anscheinend „verunreinigt“, da es jetzt eine Ressource aus einem Verzeichnis enthält, für die die Farbe durch ein anderes Verzeichnis festgelegt wird.

Um dieses Problem zu beheben, verwenden Sie die {StaticResource}-Markuperweiterung anstelle der {ThemeResource}-Markuperweiterung. Mit den angewandten Richtlinien sehen die Designverzeichnisse wie folgt aus:

<ResourceDictionary>
  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
      <SolidColorBrush x:Key="myBrush" Color="{StaticResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
      <SolidColorBrush x:Key="myBrush" Color="{StaticResource ControlFillColorDefault}"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
      <SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Beachten Sie, dass die {ThemeResource}-Markuperweiterung weiterhin im Verzeichnis „HighContrast“ anstelle der {StaticResource}-Markuperweiterung verwendet wird. Diese Situation fällt unter die Ausnahme, die weiter oben in den Richtlinien angegeben wurde. Die meisten Pinselwerte für das HighContrast-Design verwenden eine Farbauswahl, die global vom System gesteuert wird, aber für XAML als Ressource mit einem speziellen Namen (mit dem Präfix „SystemColor“) verfügbar gemacht wird. Das System ermöglicht Benutzer*innen, die spezifischen Farben festzulegen, die für ihre Kontrastdesigneinstellungen über das Center für vereinfachte Bedienung verwendet werden sollen. Diese Farbauswahl gilt für die speziell benannten Ressourcen. Das XAML-Framework verwendet das gleiche Designänderungsereignis, um auch diese Pinsel zu aktualisieren, wenn es erkennt, dass sie auf Systemebene geändert wurden. Darum wird hier die {ThemeResource}-Markuperweiterung verwendet.