Бөлісу құралы:


Ресурсы темы XAML

Ресурсы темы в XAML — это набор ресурсов, которые применяют разные значения в зависимости от того, какая системная тема активна. Существует 3 темы, поддерживаемые платформой XAML: Light, Dark и HighContrast.

Предварительные требования: В этом разделе предполагается, что вы прочли материалы ResourceDictionary и ссылки на ресурсы XAML.

Ресурсы темы v. статические ресурсы

Существует два расширения разметки XAML, которые могут ссылаться на ресурс XAML из существующего словаря ресурсов XAML: расширение разметки {StaticResource} и расширение разметки {ThemeResource}.

Оценка расширения разметки {ThemeResource} производится при загрузке приложения и каждом последующем изменении темы во время выполнения. Обычно это результат изменения параметров устройства или программного изменения в приложении, которое изменяет текущую тему.

Напротив, расширение разметки {StaticResource} вычисляется только при первой загрузке XAML приложением. Он не обновляется. Он аналогичен поиску и замене в XAML фактическим значением времени выполнения в момент запуска приложения.

Ресурсы темы в структуре словаря ресурсов

Каждый ресурс темы является частью XAML файла themeresources.xaml. В целях разработки themeresources.xaml доступен в папке \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic из установки пакета SDK для Windows. Словари ресурсов в themeresources.xaml также воспроизводятся в generic.xaml в том же каталоге.

Windows Runtime не использует эти физические файлы для поиска во время выполнения. Именно поэтому они находятся в папке DesignTime, и по умолчанию они не копируются в приложения. Вместо этого эти словари ресурсов находятся в памяти, будучи частью Windows Runtime, а ссылки на ресурсы XAML вашего приложения на ресурсы темы (или системные ресурсы) разрешаются во время работы.

Рекомендации по ресурсам для пользовательских тем

Следуйте этим рекомендациям при определении и использовании собственных ресурсов пользовательской темы:

  • Укажите словари тем для "Light" и "Dark" в дополнение к словарю HighContrast. Хотя вы можете создать ResourceDictionary с ключом "Default", лучше явно указать и вместо этого использовать «Light», «Dark» и «HighContrast».

  • Используйте расширение разметки {ThemeResource} в: стилях, сеттерах, шаблонах элементов управления, установках свойств и анимациях.

  • Не используйте расширение разметки {ThemeResource} в определениях ресурсов внутри themeDictionaries. Вместо этого используйте расширение разметки {StaticResource} .

    ИСКЛЮЧЕНИЕ. Расширение разметки {ThemeResource} можно использовать для ссылки на ресурсы, которые не зависят от темы приложения в ThemeDictionaries. Примерами этих ресурсов являются ресурсы цвета акцента, такие как SystemAccentColor, или системные цветовые ресурсы, обычно начинающиеся на "SystemColor", как SystemColorButtonFaceColor.

Caution

Если вы не следуйте этим рекомендациям, в приложении может появиться непредвиденное поведение, связанное с темами. Дополнительные сведения см. в разделе "Устранение неполадок с ресурсами темы ".

Цветовая рампа XAML и кисти, зависящие от темы

Объединенный набор цветов для тем "Свет", "Темный" и "HighContrast" составляют цветовую рампу Windows в XAML. Следует ли изменить системные темы или применить тему к собственным элементам XAML, важно понять, как структурированы цветовые ресурсы.

Дополнительные сведения о применении цвета в Windows app см. в разделе Color в приложениях Windows.

Цвета светлой и темной темы

Платформа XAML предоставляет набор именованных ресурсов Color с значениями, адаптированными для тем "Свет" и "Темная". Для WinUI ресурсы темы определяются в файле Xaml общих ресурсов темы. Имена цветов очень точно описывают их предполагаемое использование, и для каждого ресурса Color существует соответствующий SolidColorBrush.

Подсказка

Визуальный обзор этих цветов см. в приложении коллекции WinUI 3: Colors

Приложение Галерея WinUI 3 включает интерактивные примеры большинства элементов управления WinUI, функций и возможностей. Получите приложение из магазина Microsoft Store или получите исходный код в GitHub

Цвета темы контрастности системы Windows

Помимо набора ресурсов, предоставляемых платформой XAML, существует набор значений цвета, производных от системной палитры Windows. Эти цвета не относятся к приложениям Windows Runtime или Windows. Однако многие из ресурсов кисти XAML используют эти цвета, если система работает (и приложение работает) с помощью темы HighContrast. Платформа XAML предоставляет эти системные цвета в качестве ключевых ресурсов. Ключи соответствуют формату именования: SystemColor[name]Color

Дополнительные сведения о поддержке тем контрастности см. в разделе "Темы контрастности".

Цвет системного акцента

Помимо системных цветов темы контрастности, системный акцентный цвет предоставляется как специальный цветовой ресурс с ключом SystemAccentColor. Во время выполнения этот ресурс получает цвет, указанный пользователем в качестве цвета акцента в параметрах персонализации Windows.

Замечание

Хотя можно переопределить системные цветовые ресурсы, рекомендуется уважать выбор цвета пользователя, особенно для параметров контрастной темы.

Кисти, зависящие от темы

Ресурсы цвета, отображаемые в предыдущих разделах, используются для задания свойства Color ресурсов SolidColorBrush в словарях ресурсов системной темы. Ресурсы кисти используются для применения цвета к элементам XAML.

Давайте рассмотрим, как значение цвета для этой кисти определяется во время выполнения. В словарях ресурсов Light и Dark этот элемент оформления определяется следующим образом:

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

В словаре ресурсов "HighContrast" эта кисть определяется следующим образом:

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

Если эта кисть применяется к элементу XAML, его цвет определяется во время выполнения текущей темой, как показано в этой таблице.

Тема Ресурс цвета Значение среды выполнения
Light TextFillColorPrimary #E4000000
Темный TextFillColorPrimary #FFFFFFFF
HighContrast SystemColorWindowTextColor (цвет текста оконной системы) Цвет, указанный в параметрах текста.

Шкала типов XAML

Файл themeresources.xaml определяет несколько ресурсов, определяющих стиль , который можно применить к текстовым контейнерам в пользовательском интерфейсе, в частности для TextBlock или RichTextBlock. Эти стили не являются неявными по умолчанию. Они предоставляются для упрощения создания определений пользовательского интерфейса XAML, которые соответствуют пандусу типа Windows , документированному в рекомендациях по шрифтам.

Эти стили предназначены для текстовых атрибутов, которые необходимо применить ко всему текстовому контейнеру. Если вы хотите применить стили только к разделам текста, задайте атрибуты для текстовых элементов в контейнере, например в файле Run in TextBlock.Inlines или абзаце в RichTextBlock.Blocks.

Стили выглядят следующим образом при применении к TextBlock:

Стили блоков текста

Стиль Weight Size
Заголовок Регулярный 12
Тело Регулярный 14
Тело сильное Полуболд 14
Основной Большой Регулярный 18
Тело большое и сильное Полуболд 18
Подзаголовок Полуболд 20
Заголовок Полуболд 28
Большой заголовок Полуболд 40
Display Полуболд 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}"/>

Инструкции по использованию пандуса типов Windows в приложении см. в разделе "Типография" в приложениях Windows.

Дополнительные сведения о стилях XAML см. в статье WinUI на GitHub:

Подсказка

Визуальный обзор этих стилей см. в приложении коллекции WinUI 3: Typeography

BaseRichTextBlockStyle

TargetType: RichTextBlock

Предоставляет общие свойства для всех других стилей контейнеров RichTextBlock .

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

<!-- Style definition -->
<Style x:Key="BaseRichTextBlockStyle" TargetType="RichTextBlock">
    <Setter Property="FontFamily" Value="Segoe UI Variable"/>
    <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>

Примечание. Стили RichTextBlock не имеют всех стилевых решений оформления текста, которые есть у TextBlock, главным образом потому, что объектная модель документа на основе блоков для RichTextBlock упрощает применение атрибутов к отдельным текстовым элементам. Кроме того, при настройке TextBlock.Text с помощью свойства содержимого XAML создается ситуация, при которой отсутствует текстовый элемент для стилизации, поэтому вам придется стилизовать контейнер. Это не проблема для RichTextBlock , так как его текстовое содержимое всегда должно находиться в определенных текстовых элементах, таких как Абзац, где можно применять стили XAML для заголовка страницы, подзаголовки страницы и аналогичных определений текстового пандуса.

Разные именованные стили

Существует дополнительный набор определений стилей с ключами стиля, которые можно применить к стилю кнопки, отличного от типичного стиля по умолчанию.

TargetType: Button

Этот стиль предоставляет полный шаблон для кнопки , которая может быть кнопкой назад навигации для приложения навигации. Размеры по умолчанию — 40 x 40 пикселей. Чтобы настроить стили, вы можете явно задать высоту, ширину, шрифтSize и другие свойства на кнопке или создать производный стиль с помощью BasedOn.

Вот Кнопка с ресурсом NavigationBackButtonNormalStyle, примененным к ней.

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

Он будет выглядеть примерно так:

Кнопка, стильная как кнопка

TargetType: Button

Этот стиль предоставляет полный шаблон для кнопки , которая может быть кнопкой назад навигации для приложения навигации. Он похож на NavigationBackButtonNormalStyle, но его размеры составляют 30 x 30 пикселей.

Вот кнопка с примененным к ней ресурсом NavigationBackButtonSmallStyle.

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

Устранение неполадок с ресурсами темы

Если вы не следуйте рекомендациям по использованию ресурсов темы, в приложении может появиться непредвиденное поведение, связанное с темами.

Например, при открытии всплывающего меню с светлой темой части вашего темного приложения также изменяются, как если бы они были в светлой теме. Или если перейти на страницу со светлой темой, а затем вернуться, исходная темная тематическая страница (или её части) теперь выглядит так, как будто она находится в светлой теме.

Как правило, эти типы проблем возникают при предоставлении темы по умолчанию и темы HighContrast для поддержки сценариев высокой контрастности, а затем используются темы Light и Dark в разных частях приложения.

Например, рассмотрим это определение словаря тем:

<!-- 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>

Интуитивно это выглядит правильно. Вы хотите изменить цвет, который указывает на myBrush в режиме высокой контрастности, а при обычной контрастности вы полагаетесь на расширение разметки {ThemeResource}, чтобы убедиться, что myBrush соответствует правильному цвету для вашей темы. Если ваше приложение никогда не устанавливает FrameworkElement.RequestedTheme для элементов в его визуальном дереве, это обычно будет работать должным образом. Однако в вашем приложении начинаются проблемы, как только вы начнете изменять тему различных частей визуального дерева.

Проблема возникает, потому что кисти являются ресурсами общего пользования, в отличие от большинства других типов XAML. Если у вас есть 2 элемента в поддеревьях XAML с различными темами, ссылающимися на один ресурс кисти, то при обходе фреймворком каждого поддерева для обновления выражений расширения разметки {ThemeResource} изменения в общем ресурсе кисти отражаются в другом поддереве, что не является вашим предполагаемым результатом.

Чтобы устранить эту проблему, замените словарь по умолчанию отдельными словарями тем для тем "Light" и "Dark" в дополнение к 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>

Однако проблемы по-прежнему возникают, если какие-либо из этих ресурсов встраиваются в унаследованные свойства, такие как Foreground. Шаблон пользовательского элемента управления может указать цвет переднего плана элемента с помощью расширения разметки {ThemeResource}, но когда платформа распространяет унаследованное значение на дочерние элементы, она предоставляет прямую ссылку на ресурс, который был разрешен выражением расширения разметки {ThemeResource}. Это приводит к проблемам, когда фреймворк обрабатывает изменения темы оформления, проходя визуальное дерево элемента управления. Он повторно оценивает выражение расширения разметки {ThemeResource}, чтобы получить новый ресурс кисти, но пока не распространяет эту ссылку на дочерние элементы элемента управления; это происходит позже, например во время следующей меры.

В результате после обхода визуального дерева элемента управления в ответ на изменение темы платформа обходит дочерние элементы и обновляет все выражения расширения разметки {ThemeResource}, установленные на них, или объекты, заданные в их свойствах. В этом месте возникает проблема; Фреймворк обрабатывает ресурс кисти, и так как он задает его цвет с помощью расширения разметки {ThemeResource}, он переоценивается.

На этом этапе, как представляется, фреймворк исказил словарь тем, поскольку теперь в нем есть ресурс из одного словаря, для которого цвет установлен из другого словаря.

Чтобы устранить эту проблему, используйте расширение разметки {StaticResource} вместо расширения разметки {ThemeResource}. При применении рекомендаций словари тем выглядят следующим образом:

<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>

Обратите внимание, что расширение разметки {ThemeResource} по-прежнему используется в словаре HighContrast вместо расширения разметки {StaticResource}. Эта ситуация относится к исключению, приведенному ранее в рекомендациях. Большинство значений кистей, используемых для темы HighContrast, используют варианты цвета, которые глобально управляются системой, но предоставляются XAML в качестве специально именованного ресурса (те, которые имеют префикс SystemColor в имени). Система позволяет пользователю задать определенные цвета, которые следует использовать для параметров контрастной темы при помощи Центра специальных возможностей. Эти варианты цвета применяются к специально именованным ресурсам. Фреймворк XAML использует событие изменения темы, чтобы также выполнить обновление этих кистей, когда обнаруживаются изменения на уровне системы. Поэтому здесь используется расширение разметки {ThemeResource}.