Styling
Every StyledProperty
or AttachedProperty
can be targeted by styling system.
NOTE
Avalonia does not enforce validation on whether a AvaloniaProperty
can be styled. So DirectProperty
can be targeted too, but it's certainly a bad practice. See: https://github.com/AvaloniaUI/Avalonia/issues/6837
Local Styles
StyledElement.Styles
is common property to set styles for containing control instance.
<StackPanel>
<StackPanel.Styles>
<Style Selector="Button.small">
<Setter Property="FontSize" Value="12" />
</Style>
<Style Selector="Button.big">
<Setter Property="FontSize" Value="24" />
</Style>
</StackPanel.Styles>
<Button Classes="small big" Content="This Has FontSize=24" />
<Button Classes="big small" Content="This Also Has FontSize=24" />
</StackPanel>
2
3
4
5
6
7
8
9
10
11
12
13
Importing External Styles
<Styles>
<!-- style from current assembly -->
<StyleInclude Source="/Styles/AppStyles.axaml" />
<!-- style from another assembly -->
<StyleInclude Source="avares://MyApp.Shared/Styles/CommonAppStyles.axaml" />
</Styles>
2
3
4
5
6
Selector Syntax
Selector syntax is pretty similar to CSS, which could perform hierarchic querying, class querying as well as identifier querying, in a flexible combination.
MyControl
: exact type queryMyControl, AnotherControl
: multiple query separated by commaMyControl.myclass
: class queryMyControl:focus
: pseudo class query, see Pseudo classes for details#MyName
:Name
identifier queryStackPanel > Button.myclass
: direct children queryButton[IsPressed=true]
: property query:is(MyControl)
: type query(including derived controls):is(Control).myclass
: type-less query since any control is ofControl
TIP
.
was taken for class query, so avalonia uses |
to access control type from namespace in Selector
property string, <namespace>|MyControl
for example.
NOTE
See Selector Syntax
Styling on Pseudo-Classes
To override value on selector with pseudo-class, avalonia requires some trick syntax /template/ ...
. Because all styles have lower priority than local property assignment in xaml, while pseudo class is a event-like status that should be evaluated on runtime. In the following example, if a Button
has been declared as <Button Background="Blue" />
, the first attempt with Selector="Button:pointerover"
would fail because the local assignment has the highest priority. That's why we need a dedicated syntax /template/
to target the nested presenter type, which is the real presentation of the Button
, this way distinguished the Selector
so we can make it work on :pointerover
status. So the presenter is like a shadow for the Button
, they are really the container and being contained, we just need a way to let the styling system know it's something different so that it can manage the priority separately.
<Style Selector="Button">
<Setter Property="Background" Value="Salmon" />
</Style>
<!-- you can't evaluate the effect of a style that has a lower priority -->
<Style Selector="Button:pointerover">
<Setter Property="Background" Value="Aquamarine" />
</Style>
<!-- let styling system style on ContentPresenter instead -->
<Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="Aquamarine" />
</Style>
2
3
4
5
6
7
8
9
10
11
12
13
NOTE
See: