Документация по Avalonia UI
< Все темы
Печать

Стили

Стили в Avalonia используются для обмена настройками свойств между элементами управления. Систему стилей Avalonia можно рассматривать как сочетание стилей CSS и стилей WPF/UWP. По своей сути стиль состоит из селектора и набора сеттеров.

Следующий стиль выбирает любой TextBlock в окне с классом стиля h1 и устанавливает для него размер шрифта 24 пункта и полужирный шрифт:

<Style Selector="TextBlock.h1">
    <Setter Property="FontSize" Value="24"/>
    <Setter Property="FontWeight" Value="Bold"/>
</Style>

Стили можно определить для любого элемента управления или объекта Application, добавив их в коллекции Control.Styles или Application.Styles.

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Styles>
        <Style Selector="TextBlock.h1">
            <Setter Property="FontSize" Value="24"/>
            <Setter Property="FontWeight" Value="Bold"/>
        </Style>
    </Window.Styles>

    <TextBlock Classes="h1">I'm a Heading!</TextBlock>
</Window>

Стили также можно включать из других файлов с помощью класса StyleInclude, например:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Styles>
        <StyleInclude Source="/CustomStyles.xaml" />
    </Window.Styles>

    <TextBlock Classes="h1">I'm a Heading!</TextBlock>
</Window>

Где CustomStyles.xaml — это XAML-файл с корнем Style или Styles, включенный в приложение в качестве актива, например:

CustomStyles.xaml

<Styles xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style Selector="TextBlock.h1">
        ...
    </Style>
</Styles>

Обратите внимание, что в отличие от WPF/UWP стили не будут иметь никакого эффекта, если они будут добавлены в элемент управления или ResourceDictionary приложения. Это связано с тем, что порядок определения стилей в Avalonia важен, а ResourceDictionary является несортированным словарем.

Классы стиля

Как и в CSS, элементам управления могут быть присвоены классы стилей, которые можно использовать в селекторах. Классы стилей можно назначать в XAML, задав для свойства Classes список строк, разделенных пробелами. В следующем примере классы стилей h1 и blue применяются к кнопке:

<Button Classes="h1 blue"/>

Если вам нужно добавить или удалить класс по условию, вы можете использовать следующий специальный синтаксис:

<Button Classes.accent="{Binding IsSpecial}" />

Классами стилей также можно манипулировать в коде с помощью коллекции Classes:

control.Classes.Add("blue");
control.Classes.Remove("red");

Псевдоклассы

Также, как и в CSS, элементы управления могут иметь псевдоклассы; это классы, которые определяются самим элементом управления, а не пользователем. Псевдоклассы начинаются с символа :.

Одним из примеров псевдокласса является :pointerover (похожий на :hover в CSS).

Псевдоклассы обеспечивают функциональность триггеров в WPF и VisualStateManager в UWP:

<StackPanel>
  <StackPanel.Styles>
    <Style Selector="Border:pointerover">
      <Setter Property="Background" Value="Red"/>
    </Style>
  </StackPanel.Styles>
  <Border>
    <TextBlock>I will have red background when hovered.</TextBlock>
  </Border>
</StackPanel>

Другой пример, связанный с изменением свойств внутри шаблона элемента управления:

<StackPanel>
  <StackPanel.Styles>
    <Style Selector="Button:pressed /template/ ContentPresenter">
        <Setter Property="TextBlock.Foreground" Value="Red"/>
    </Style>
  </StackPanel.Styles>
  <Button>I will have red text when pressed.</Button>
</StackPanel>

Другие псевдоклассы включают :focus, :disabled, :pressed для кнопок, :checked для флажков и т. д.

Пользовательские псевдоклассы

Вы можете создавать собственные псевдоклассы для CustomControl или TemplatedControl. Приведенная ниже функция добавляет или удаляет псевдокласс в зависимости от логического значения в StyledElement.

PseudoClasses.Set(":className", bool);

Помните: псевдоклассы всегда начинаются с :!

Селекторы

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

Селектор Описание
Button Выбирает все элементы управления Button
Button.red Выбирает все элементы управления Button с классом стиля red.
Button.red.large Выбирает все элементы управления Button с классами стиля red и large.
Button:focus Выбирает все элементы управления Button с помощью псевдокласса :focus.
Button.red:focus Выбирает все элементы управления Button с помощью класса стиля red и псевдокласса :focus.
Button#myButton Выбирает элемент управления Button с именем myButton.
StackPanel Button.foo Выбирает все Button с классом foo, которые являются потомками StackPanel.
StackPanel > Button.foo Выбирает все Button с классом foo, которые являются дочерними элементами StackPanel.
Button /template/ ContentPresenter Выбирает все элементы управления ContentPresenter внутри шаблона Button.

Для получения дополнительной информации см. документацию по селекторам.

Сеттеры

Установщики стиля описывают, что произойдет, когда селектор совпадет с элементом управления. Это простые пары свойство/значение, записанные в формате:

<Setter Property="FontSize" Value="24"/>
<Setter Property="Padding" Value="4 2 0 4"/>

Вы также можете использовать расширенный синтаксис для объявления более сложных значений объекта:

<Setter Property="MyProperty">
   <MyObject Property1="My Value"/>
</Setter>

Привязки также могут применяться с помощью сеттеров и могут привязываться к целевому элементу управления DataContext:

<Setter Property="FontSize" Value="{Binding SelectedFontSize}"/>

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

Обратите внимание, что Setter создает один экземпляр Value, который будет применяться ко всем элементам управления, которым соответствует стиль: если объект является изменяемым, изменения будут отражены во всех элементах управления. Исходя из этого, любые привязки к объекту в установщике Value не будут иметь доступа к DataContext целевого элемента управления, поскольку может быть несколько целевых элементов управления:

<Style Selector="local|MyControl">
  <Setter Property="MyProperty">
     <MyObject Property1="{Binding MyViewModelProperty}"/>
  </Setter>
</Style>

В приведенном выше примере источником привязки будет MyObject.DataContext, а не MyControl.DataContext, и если MyObject не имеет контекста данных, то привязка не сможет создать значение.

Примечание: в настоящее время, если вы используете скомпилированные привязки, вам необходимо явно указать тип данных источника привязки в элементе <Style>:

<Style Selector="MyControl" x:DataType="MyViewModelClass">
  <Setter Property="ControlProperty" Value="{Binding MyViewModelProperty}" />
</Style>

Шаблоны в сеттерах

Как упоминалось выше, обычно создается один экземпляр сеттера Value, который используется всеми соответствующими элементами управления. В связи с этим, чтобы использовать элемент управления в качестве значения установки, элемент управления должен быть заключен в <Template>:

<Style Selector="Border.empty">
  <Setter Property="Child">
    <Template>
      <TextBlock>No content available.</TextBlock>
    </Template>
  </Setter>
</Style>

Приоритет стиля

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

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Styles>
        <Style Selector="TextBlock.h1">
            <Setter Property="FontSize" Value="24"/>
            <Setter Property="FontWeight" Value="Bold"/>
        </Style>
    </Window.Styles>

    <StackPanel>
        <StackPanel.Styles>
            <Style Selector="TextBlock.h1">
                <Setter Property="FontSize" Value="48"/>
                <Setter Property="Foreground" Value="Red"/>
            </Style>
        </StackPanel.Styles>

        <TextBlock Classes="h1">
            <StackPanel.Styles>
                <Style Selector="TextBlock.h1">
                    <Setter Property="Foreground" Value="Blue"/>
                </Style>
            </StackPanel.Styles>

            I'm a Heading!
        </TextBlock>
    </StackPanel>
</Window>

Здесь стиль h1 определен в нескольких местах. TextBlock будет иметь следующие настройки:

Свойство Значение Источник
FontSize 48 StackPanel
FontWeight Bold Window
Foreground Blue TextBlock

Если к свойству применяется более одного установщика стиля, значение, которому будет отдан приоритет, будет:

  • Значение из стиля, определенного в предке, ближайшем к элементу управления.
  • Для двух стилей, объявленных в одной коллекции Styles, стиль, который появляется позже
Оглавление