Перейти к основному содержимому
Версия: 0.10.x

Styles

Styles in Avalonia are used to share property settings between controls. The Avalonia styling system can be thought of as a mix of CSS styling and WPF/UWP styling. At its most basic, a style consists of a selector and a collection of setters.

A style applies to the control that it is defined on and all descendent controls.

The following style selects any TextBlock with a h1 style class and sets its font size to 24 point and font weight to bold:

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

Styles can be defined on any control or on the Application object by adding them to the Control.Styles or Application.Styles collections.

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

Styles can also be included from other files using the StyleInclude class, e.g.:

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

Where CustomStyles.xaml is a XAML file with a root of either Style or Styles and is included as an asset in the application, e.g.:

CustomStyles.xaml

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

Note that unlike WPF/UWP, styles will have no effect if they're added to a control or application ResourceDictionary. This is because the order that styles are defined in Avalonia is important and ResourceDictionary is an unsorted dictionary.

Style Classes

As in CSS, controls can be given style classes which can be used in selectors. Style classes can be assigned in XAML by setting the Classes property to a space-separated list of strings. The following example applies the h1 and blue style classes to a Button:

<Button Classes="h1 blue"/>

If you need to add or remove class by condition, you can use the following special syntax:

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

Style classes can also be manipulated in code using the Classes collection:

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

Pseudoclasses

Also as in CSS, controls can have pseudoclasses; these are classes that are defined by the control itself rather than by the user. Pseudoclasses start with a : character.

One example of a pseudoclass is the :pointerover (similar to :hover in CSS).

Pseudoclasses provide the functionality of Triggers in WPF and VisualStateManager in 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>

Another example that involves changing properties inside of control template:

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

Other pseudoclasses include :focus, :disabled, :pressed for buttons, :checked for checkboxes etc.

Custom PseudoClasses

You can create own pseudoclasses for your CustomControl or TemplatedControl. The function below adds or remove a pseudoclass depending on a boolean value on a StyledElement.

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

Remember: PseudoClasses always starts with a :!

Selectors

Selectors select a control using a custom selector syntax which is very similar to the syntax used for CSS selectors. An example of some selectors:

SelectorDescription
ButtonSelects all Button controls
Button.redSelects all Button controls with the red style class
Button.red.largeSelects all Button controls with the red and large style classes
Button:focusSelects all Button controls with the :focus pseudoclass
Button.red:focusSelects all Button controls with the red style class and the :focus pseudoclass
Button#myButtonSelects a Button control with a name of myButton
StackPanel Button.fooSelects all Buttons with the foo class that are descendants of a StackPanel
StackPanel > Button.fooSelects all Buttons with the foo class that are children of a StackPanel
Button /template/ ContentPresenterSelects all ContentPresenter controls inside of Button's template

For more information see the selectors documentation.

Setters

A style's setters describe what will happen when the selector matches a control. They are simple property/value pairs written in the format:

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

You can also use long-form syntax to declare more complex object values:

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

Bindings can also be applied using setters and can bind to the target control's DataContext:

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

Whenever a style is matched with a control, all of the setters will be applied to the control. If a style selector causes the style to no longer match a control, the property value will revert to the its next highest priority value.

Note that the Setter creates a single instance of Value which will be applied to all controls that the style matches: if the object is mutable then changes will be reflected on all controls. Following on from this, any bindings on an object within the setter Value will not have access to the target control's DataContext as there may be multiple target controls:

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

In the above example, the binding source will be MyObject.DataContext, not MyControl.DataContext and if MyObject has no data context then the binding will not be able to produce a value.

Note: at present, if you are using compiled bindings, you need to explicitly set the data type of the binding source in the <Style> element:

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

Templates in Setters

As mentioned above, usually a single instance of a setter's Value is created and shared across all matching controls. Due to this, to use a control as a setter value, the control must be wrapped in a <Template>:

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

Style Precedence

If multiple styles match a control, and they both attempt to set the same property then the style closest to the control will win. Consider the following example:

<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">
<TextBlock.Styles>
<Style Selector="TextBlock.h1">
<Setter Property="Foreground" Value="Blue"/>
</Style>
</TextBlock.Styles>

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

Here the h1 style is defined in multiple places. The TextBlock will end up with the following settings:

PropertyValueSource
FontSize48StackPanel
FontWeightBoldWindow
ForegroundBlueTextBlock

If more than one style setter applies to a property, the value that takes precedence will be:

  • The value from the style defined in the ancestor closest to the control
  • For two styles declared in the same Styles collection, the style that appears later