Стили XAML

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

WinUI и стили

Начиная с WinUI 2.2, мы использовали библиотеку пользовательского интерфейса Windows (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 (кнопка вызвана), или Disabled (кнопка не активна). Эти окончания добавляются к исходным именам упрощенного стиля: 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"/>

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

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

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

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

Например, если вы пишете элемент управления, похожий на Button, вы можете напрямую ссылаться на ресурсы кнопки следующим образом:

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

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

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

Его требуется использовать ThemeDictionary , который дублируется три раза для правильной обработки трех различных изменений темы (Default, , LightHighContrast).

Внимание!

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

Предотвращение рестайлинга элементов управления

Библиотека пользовательского интерфейса Windows 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

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