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"/>
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
pseudoclass (:hover
in CSS - we may change to that in future).
Pseudoclasses provide the functionality of Triggers
in WPF and
VisualStateManager
in UWP:
<StackPanel>
<StackPanel.Styles>
<Style Selector="Button:pointerover">
<Setter Property="Button.Foreground" Value="Red"/>
</Style>
</StackPanel.Styles>
<Button>I will have red text when hovered.</Button>
</StackPanel>
Other pseudoclasses include :focus
, :disabled
, :pressed
for buttons,
:checked
for checkboxes etc.
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:
Selector | Description |
---|---|
Button |
Selects all Button controls |
Button.red |
Selects all Button controls with the red style class |
Button.red.large |
Selects all Button controls with the red and large style classes |
Button:focus |
Selects all Button controls with the :focus pseudoclass |
Button.red:focus |
Selects all Button controls with the red style class and the :focus pseudoclass |
Button#myButton |
Selects a Button control with a name of myButton |
StackPanel Button.foo |
Selects all Button s with the foo class that are descendants of a StackPanel |
StackPanel > Button.foo |
Selects all Button s with the foo class that are children of a StackPanel |
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"/>
Whenever a style is matched with a control, all of the setters will be applied to the control. If a style selector should no longer match a control, the property value will revert to its previous value.
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">
<StackPanel.Styles>
<Style Selector="TextBlock.h1">
<Setter Property="Foreground" Value="Blue"/>
</Style>
</StackPanel.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:
Property | Value | Source |
---|---|---|
FontSize |
48 | StackPanel |
FontWeight |
Bold | Window |
Foreground |
Blue | TextBlock |
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