Net cross-platform UI framework Avalonia introduction - detailed style explanation

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.

Insert image description here

Modify the properties Design.PreviewWithof 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

Insert image description here

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.

Insert image description here

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.DataContexttags 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
Insert image description here

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 StyleDefine Style Setterto define specific control properties and values, and then Selectordefine the name of a style through a selector.

Style use, Classesuse 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:
Insert image description here

Style selector (Selector) syntax

In avalonia style, Setterthe definition of properties and values ​​is the same as in WPF, and the selector Selectoris 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 Classesto 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>

Insert image description here

2. Define the style name

Define the name of the style in the selector Selector="ControlType(控件类型).Name(样式名称)", and then Classesuse 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>

Insert image description here

3. Use multiple styles at the same time

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

Insert image description here

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

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

Insert image description here

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.
Please add image description

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:
Please add image description

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.Please add image description

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

Please add image description

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

Insert image description here

7. Control the internal style of the control template

Most controls in Avalonia are inherited from TemplatedControlcontrols and have properties defined in the default control theme (ControlTheme) Template. Sometimes you need to write your own styles and directly operate Templaethe controls inside.

And many pseudo-class styles in the source code, such as pointerover, , pressedetc., have already defined basic styles, so the Buttonpseudo-class styles of controls such as those defined above are invalid.
Insert image description here

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

Insert image description here

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:
Please add image description

Guess you like

Origin blog.csdn.net/qq_39427511/article/details/132776654