Стили XAML

Вы можете настроить внешний вид приложений различными способами с помощью платформы XAML. Стили позволяют задавать свойства элемента управления и повторно использовать эти параметры для согласованного внешнего вида в нескольких элементах управления.

WinUI и стили

Начиная с WinUI 2.2, мы использовали WinUI для доставки новых обновлений визуального стиля в компонентах пользовательского интерфейса. Если пользовательский интерфейс не обновляется до последних стилей, обязательно обновите его до последнего пакета NuGet WinUI.

Начиная с WinUI 2.6, мы предоставляем новые стили для большинства элементов управления и новую систему управления версиями, которая позволяет вернуться к предыдущим стилям элементов управления при необходимости. Мы рекомендуем использовать новые стили, так как они лучше соответствуют направлению дизайна Windows. Однако если сценарий не может поддерживать новые стили, предыдущие версии по-прежнему доступны.

Вы можете изменить версию стиля, задав ControlsResourcesVersion свойство, XamlControlsResources которое вы включаете в себя Application.Resources при использовании WinUI версии 2. ControlsResourcesVersion значение перечисления Version2по умолчанию.

Установка этого значения Version1 приводит XamlControlsResources к загрузке предыдущих версий стилей вместо новых стилей, используемых последней версией WinUI. Изменение этого свойства во время выполнения не поддерживается, и функция горячей перезагрузки VisualStudio не будет работать; Однако после перестроения приложения вы увидите изменения стилей элементов управления.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" 
                           ControlsResourcesVersion="Version1"/>
</Application.Resources>

Основы стиля

Используйте стили для извлечения параметров визуального свойства в многократно используемые ресурсы. В следующем примере показаны три кнопки со стилем, задающим свойства BorderBrush, BorderThickness и Foreground. Применяя стиль, можно сделать элементы управления одинаковыми, не устанавливая эти свойства для каждого элемента управления отдельно.

Снимок экрана: три стилизованные кнопки, расположенные горизонтально.

Вы можете определить встроенный стиль в XAML для элемента управления или как повторно используемый ресурс. Определите ресурсы в XAML-файле отдельной страницы в файле App.xaml или в отдельном файле XAML словаря ресурсов. Файл XAML словаря ресурсов можно совместно использовать для приложений, а несколько словарей ресурсов можно объединить в одном приложении. Где определяется ресурс, определяет область, в которой ее можно использовать. Ресурсы уровня страницы доступны только на странице, в которой они определены. Если ресурсы с одинаковым ключом определены как в App.xaml, так и на странице, ресурс на странице переопределяет ресурс в App.xaml. Если ресурс определен в отдельном файле словаря ресурсов, то область его использования зависит от того, на что ссылается словарь ресурсов.

В определении Style требуется атрибут TargetType и коллекция одного или нескольких элементов Setter. Атрибут TargetType является строкой, задающей тип FrameworkElement, к которому применяется стиль. Значение TargetType должно указать тип, производный от FrameworkElement, который определяется среда выполнения Windows или настраиваемым типом, доступным в указанной сборке. Если вы пытаетесь применить стиль к элементу управления, а тип элемента управления не соответствует атрибуту TargetType стиля, которое вы пытаетесь применить, возникает исключение.

Для каждого элемента Setter необходимы параметры Property и Value. Эти параметры свойств указывают, к какому свойству элемента управления применяется параметр, и значением, заданным для этого свойства. Параметр Setter.Value можно задать с помощью синтаксиса атрибута или элемента свойства. В XAML здесь показан стиль, применяемый к кнопкам, показанным ранее. В этом коде XAML для первых двух элементов Setter используется синтаксис атрибута, а в последнем элементе Setter (для свойства BorderBrush) — синтаксис элемента свойства. В примере не используется атрибут атрибута x:Key, поэтому стиль неявно применяется к кнопкам. Применение стилей неявно или явно описано в следующем разделе.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

Применение неявного или явного стиля

Если вы определяете стиль как ресурс, к элементам управления можно применить два способа:

  • неявно, когда указывается только атрибут TargetType для элемента Style;
  • явно, когда указываются атрибуты TargetType и x:Key для элемента Style, а затем в свойстве Style нужного элемента управления задается ссылка на расширение разметки {StaticResource}, которая использует явный ключ.

Если стиль содержит атрибут x:Key, то его можно применить к элементу управления только путем задания стиля с ключом в свойстве Style элемента управления. В отличие от этого, стиль без атрибута x:Key автоматически применяется к каждому элементу управления его целевого типа, который в противном случае не имеет явного параметра стиля.

Ниже приведены две кнопки, демонстрирующие неявные и явные стили.

неявно и явно стилистики кнопок.

В этом примере первый стиль содержит атрибут x:Key и имеет тип целевого объекта Button. Данный ключ задается в свойстве Style и поэтому стиль применяется явным образом. Второй стиль применяется неявно ко второй кнопке, так как его целевой тип — Button , а стиль не имеет атрибута x:Key.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

Использование стилей на основе

Чтобы упростить обслуживание стилей и оптимизировать повторное использование стилей, можно создавать стили, наследуемые от других стилей. Для создания производных стилей служит свойство BasedOn. Стили, наследуемые от других стилей, должны нацелены на тот же тип элемента управления или элемент управления, производный от типа, предназначенного для базового стиля. Например, если базовый стиль применяется к элементу ContentControl, то основанные на нем стили могут применяться к элементу ContentControl или к типам, производным от ContentControl, например Button и ScrollViewer. Если значение не задано в стиле на основе, оно наследуется от базового стиля. Чтобы изменить значение из базового стиля, стиль на основе переопределяет это значение. В следующем примере показаны классы Button и CheckBox со стилями, производными от одного базового стиля.

стили кнопок, основанных на стилях.

В базовом стиле целевым типом является ContentControl и заданы свойства Height и Width. В стилях, основанных на этом стиле, целевыми типами будут CheckBox и Button, производные от ContentControl. Производные стили задают новые цвета для свойств BorderBrush и Foreground. (Обычно вы не ставите границу вокруг CheckBox. Мы делаем это здесь, чтобы показать эффекты стиля.)

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

Использование средств для работы со стилями легко

Быстрый способ применить стили к элементам управления — щелкнуть правой кнопкой мыши элемент управления в области конструктора XAML Microsoft Visual Studio и выбрать пункт "Изменить стиль " или "Изменить шаблон " (в зависимости от элемента управления, который вы щелкаете правой кнопкой мыши). Затем можно применить существующий стиль, выбрав "Применить ресурс " или определив новый стиль, выбрав "Создать пустое". Если вы создаете пустой стиль, вы можете определить его на странице, в файле App.xaml или в отдельном словаре ресурсов.

Упрощенная стилизация

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

Снимок экрана с двумя кнопками: одна из них неактивна, а к другой применена упрощенная стилизация.

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

Для таких состояний, как PointerOver (наведите указатель мыши на кнопку), PointerPressed (кнопка была вызвана), или отключено (кнопка не взаимодействует). Эти окончания добавляются в исходные имена упрощенного стиля: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled и т. д. Изменение этих кистей также гарантирует, что элементы управления цветом последовательно соответствуют теме приложения.

Размещение этих кистей переопределяется на уровне App.Resources , изменит все кнопки в приложении, а не на одной странице.

Стилизация для каждого элемента управления

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

Снимок экрана: три стилизованные кнопки, расположенные вертикально.

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

Это повлияет только на то, что на странице, где существовал этот элемент управления, один элемент управления "Специальный флажок".

Пользовательские элементы управления

При создании собственных пользовательских элементов управления, которые могут быть визуально и (или) функционально согласованы со встроенными элементами управления, рекомендуется использовать неявные ресурсы стилей и упрощенных стилей для определения пользовательского содержимого. Вы можете использовать ресурсы напрямую или создать новый псевдоним для ресурса.

Использование ресурсов управления напрямую

Например, если вы пишете элемент управления, который выглядит как Кнопка, вы можете ссылаться на ресурсы кнопки напрямую, как показано ниже.

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

Псевдонимирование ресурсов управления новыми именами

Кроме того, если вы предпочитаете создавать собственные ресурсы, следует псевдонимировать эти пользовательские имена для наших ресурсов упрощенного стиля по умолчанию.

Например, стиль пользовательского элемента управления может иметь специальные определения ресурсов:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

В словаре ресурсов или главном определении можно подключить ресурсы упрощенного стиля к пользовательским:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Для правильной обработки трех разных изменений темы (, , Light) HighContrastтребуется использовать ThemeDictionary повторяющийся три раза.Default

Внимание

Если вы назначаете ресурс упрощенной стилизации новому псевдониму, а также переопределяете ресурс упрощенного стиля, настройка может не применяться, если поиск ресурсов не соответствует правильному порядку. Например, если переопределить ButtonBackground в месте, которое выполняется поиск до MyCustomControlBackground его обнаружения, переопределение будет пропущено.

Избегайте перебора элементов управления

WinUI 2.2 или более поздней версии включает новые стили и шаблоны для элементов управления WinUI и системы.

Лучший способ оставаться в курсе наших последних визуальных стилей — использовать последний пакет WinUI 2 и избегать пользовательских стилей и шаблонов (также известных как повторное шаблонирование). Стили по-прежнему удобно применять набор значений последовательно между элементами управления в приложении. При этом обязательно на основе наших последних стилей.

Для системных элементов управления, использующих стили WinUI (Windows.UI.Xaml.Controls пространство имен), задайте , BasedOn="{StaticResource Default<ControlName>Style}"где <ControlName> находится имя элемента управления. Например:

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

Для элементов управления WinUI 2 (Microsoft.UI.Xaml.Controls пространство имен) стиль по умолчанию определяется в метаданных, поэтому опустить BasedOnего.

Производные элементы управления

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

  • Создайте новый стиль с помощью targetType , установленного для пользовательского элемента управления.
  • На основе стиля по умолчанию производного элемента управления.

Один из распространенных сценариев заключается в том, чтобы получить новый элемент управления из ContentDialog. В этом примере показано, как создать новый стиль, который применяется DefaultContentDialogStyle к пользовательскому диалогу.

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

Свойство шаблона

Вы можете использовать метод задания стиля для свойства Template класса Control. По сути, сюда входит большинство типовых стилей XAML и ресурсов XAML приложения. Это подробно рассматривается в шаблонах элементов управления разделами.