Using the designer
Designer preview
In window and usercontrol, the control is modified in the code. If the code is correct, the changes can be seen in real time in the designer. However, in the style (Styles) file, you cannot see it directly. You need to use the designer to preview the tag Design.PreviewWith
.
Modify the properties Design.PreviewWith
of Border and set the preview area size inPadding
<Design.PreviewWith>
<Border Width="500" Height="500" Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>
Just add the controls that need to be previewed inside the Border
If you want to preview multiple controls, just like in WPF, first add a layout control to the Border, and then put as many as you like in the layout control.
Binding preview
In the V11 version, the mvvm mode is used by default, so many attributes are implemented through binding. However, if you need to preview during the development process, you need to use Design.DataContext
tags and put the opposite viewmodel inside.
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainViewModel />
</Design.DataContext>
Note: This is for preview only. If you need to run the binding, you need to set it elsewhere.
According to the code comments, you can know: This only sets the previewer in the IDE DataContext
. To set the actual runtime DataContext
, please set the property in the code DataContext
(view app.axaml.cs)
Set in app.axaml.cs
styles, resources
For the definition and reference of styles and resource files, see another article: Getting Started with Net Cross-Platform UI Framework Avalonia - Resources and Styles
style
Style basics
A basic definition of a style. Use Style
Define Style Setter
to define specific control properties and values, and then Selector
define the name of a style through a selector.
Style use, Classes
use the style in the control through
Official template:
<Style Selector="selector syntax">
<Setter Property="property name" Value="new value"/>
...
</Style>
Example
<UserControl ....>
<UserControl.Styles>
<Style Selector="Button.btn1">
<Setter Property="Background" Value="Red"/>
</Style>
</UserControl.Styles>
<Grid>
<Button Classes="btn1" Content="12345"/>
</Grid>
</UserControl>
Effect:
Style selector (Selector) syntax
In avalonia style, Setter
the definition of properties and values is the same as in WPF, and the selector Selector
is more similar to the syntax used in CSS.
1. Selector defines control type
Selector="ControlType(控件类型)"
Indicates that such controls in the style application scope use this style by default, and the control does not need to be written Classes
to use the style.
<Style Selector="Button">
Example:
<UserControl ....>
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="Red"/>
</Style>
</UserControl.Styles>
<Grid>
<Button Content="12345"/>
</Grid>
</UserControl>
2. Define the style name
Define the name of the style in the selector Selector="ControlType(控件类型).Name(样式名称)"
, and then Classes
use the corresponding style by
<!--定义-->
<Style Selector="Button.btn1"></Style>
<!--使用-->
<Button Classes="btn1"/>
Example:
<UserControl ....>
<UserControl.Styles>
<Style Selector="Button.btn1">
<Setter Property="Background" Value="Red"/>
</Style>
</UserControl.Styles>
<Grid>
<Button Classes="btn1" Content="12345"/>
</Grid>
</UserControl>
3. Use multiple styles at the same time
Classes
Write multiple style names separated by spaces in
Classes="style1 style2"
Example:
<UserControl ...>
<UserControl.Styles>
<Style Selector="Button.btn1">
<Setter Property="Background" Value="Red"/>
</Style>
<Style Selector="Button.btn2">
<Setter Property="Foreground" Value="White"/>
</Style>
</UserControl.Styles>
<Grid>
<Button Classes="btn1 btn2" Content="12345"/>
</Grid>
</UserControl>
Effect:
4. Implementation of interactive state effects
Special states such as control hovering, pressing, getting focus, etc. are implemented in Avalonia through pseudo classes (Pseudo Classes). The names of pseudo classes in the selector always start with a colon.
The relevant pseudo-classes available in Avalonia are as follows:
Pseudo class | describe |
---|---|
:pointerover |
Pointer input is currently hovering over (inside the bounds of the control) |
:focus |
The control has input focus |
:disabled |
Control does not respond to user interaction |
:pressed |
Button control is pressed |
:checked |
Checkbox control is selected (shows a check mark) |
You can also define it yourself if conditions permit. Pseudo Classes
Use pseudo-classes to define styles
Selector
Both direct Selector="ControlType(控件类型):PseudoClasses(伪类)"
and Selector="ControlType(控件类型).Name(样式名称):PseudoClasses(伪类)"
two definition methods are available. The usage method is the same as above, take effect directly or use the style name.
Example:
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="Red"/>
</Style>
<Style Selector="Border.bd1:pointerover">
<Setter Property="Background" Value="Red"/>
</Style>
Effect:
Pitfalls of using pseudo-classes
1. The Border must have content or the background has an initialization value, otherwise the entry effect cannot be triggered. The mouse is placed in a blank area.
solution:
Add default values to properties in styles
Note: You cannot directly assign a default value to the control, otherwise it will not be triggered.
Two ways of writing:
write another style
<Style Selector="Border">
<Setter Property="Background" Value="White"/>
</Style>
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="Red"/>
</Style>
Effect:
Another one: nested styles (see the nested styles section below), the effect is the same
2. Another pitfall is other controls, such as Button. Using pseudo-classes to directly change the Button properties is still ineffective.
As follows, setting the hover color to red, but it is ineffective.
This is related to the writing method and working principle of avalonia style. The controls in the selector control template (template) are written in detail below.
5. Nested styles
Define a Style in Style, the inner one Selector
continues the outer one Selector
, and is used ^
to replace the content of the previous selector.
<Style Selector="Border">
<Setter Property="Background" Value="White"/>
<Style Selector="^:pointerover">
<Setter Property="Background" Value="Red"/>
</Style>
</Style>
Effect:
You can see that its effect is the same as the effect of separating the two styles below.
<Style Selector="Border">
<Setter Property="Background" Value="White"/>
</Style>
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="Red"/>
</Style>
6. Add attribute conditions to styles
To make the style take effect under certain conditions, you can add it to the Selector [Property=value]
to limit the conditions.
Example:
<UserControl ...>
<UserControl.Styles>
<Style Selector="Button[Content=12345]">
<Setter Property="Background" Value="Green"/>
</Style>
<Style Selector="Button.btn1[Content=123456]">
<Setter Property="Background" Value="Green"/>
</Style>
</UserControl.Styles>
<StackPanel>
<Button Content="12345"/>
<Button Content="123"/>
<Button Classes="btn1" Content="123456"/>
</StackPanel>
</UserControl>
Effect
7. Control the internal style of the control template
Most controls in Avalonia are inherited from TemplatedControl
controls and have properties defined in the default control theme (ControlTheme) Template
. Sometimes you need to write your own styles and directly operate Templae
the controls inside.
And many pseudo-class styles in the source code, such as pointerover
, , pressed
etc., have already defined basic styles, so the Button
pseudo-class styles of controls such as those defined above are invalid.
If you want to control and modify the styles of some controls in the Template (directly writing the styles will not take effect), it is best to have a copy of the source code of Avalonia and modify it according to the source code. The picture below is the source code of a button (in the Controls folder of the Avalonia.Themes.Fluent project).
When writing Selector Selector="控件类型:伪类 /template/ 内部控件的类型#内部控件的名称"
, if the internal control type is unique, you do not need to write the name of the internal control.
The following example writes a style that turns red when hovering. The following writing methods are all correct and can be freely combined with the previous syntax.
<Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="Red"/>
</Style>
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresente">
<Setter Property="Background" Value="Red"/>
</Style>
<Style Selector="Button.btn1:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Red"/>
</Style>
Achieved effects: