Стили
Стили в 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
, стиль, который появляется позже