Style

# Style Syntax

The basic syntax of a style is as follows:

selector {
    // setter-property: setter-value;        // Use value.
    // setter-property: var(resource-key);   // Use dynamic resource.
    
    // Sample:
    Background: #0068B5;
    Foreground: var(Accent);
    
    // ...
    
    // Children must be at last of the style.
    [[
        ::animation{
            
        }
        child-style-selector {
            // ...
        }
        child-style-selector2 {
            // ...
        }
    ]]
}

Like Avalonia styles, Acss styles can be nested, and nested styles are placed in Children with the syntax of two pairs of parentheses '[[ ...]]'. In addition to child styles, children can also have animations.

Selector Syntax

The syntax of Acss's Selector is exactly the same as in Avalonia. The only difference is that you don't need to add the "^" symbol in front of the Selector of a sub-style.

Setter Syntax

The form in which the Setter is placed in the style has already been shown. The other features are described separately here.

  • The whitespace before and after the colon ":" in a Setter does not affect the effect of the statement.

  • The ";" character at the end of a Setter is essential, but is not required for collection properties, or can be omitted from the last Setter.

  • A Setter's Property is case sensitive.

  • A Setter's Value can use dynamic resources.

  • The parsing syntax of a Setter's Value is consistent with the parsing syntax of resource values.

  • A Setter's Value can use static instances, using the "@" symbol to mark static types and then accessing static properties directly, for example:

// ...
TextDecorations: @TextDecorations.Strikethrough;
// ...
  • There is a special syntax for defining values for Setter's collection types. For example, for the Transitions property, it is a collection.

// Defines a collection object Transitions with three Transitions assigned to the Transitions property.
// Where the first is a directly defined Transition and the second and third are accessed dynamic resources.
Transitions:[
    RenderTransform 0.075 0 LinearEasing.
    var(stRenderTransform); var(stBorderBrush;)
    var(stBorderBrush); var(stBorderBrush).
]

Classification of styles

Acss styles still end up generating Avalonia styles to produce the effect. But logically we still categorise it.

The discussion here is of the root style, not including sub-styles nested within the style.

1. Theme sub-styles

A theme sub-style is a sub-style defined for a type of Control that, when parsed into an Avalonia style, looks up the ControlTheme for that type of Control in the current environment and Application scope and adds the style to that ControlTheme as a sub-style.

This is not unlike when you define a sub-style directly in the ControlTheme.

In the following three pieces of code, in practical terms, Code #1 + Code #2 = Code #3.

<!-- Code #1 -->
<ControlTheme x:Key="{x:Type Button}" TargetType="Button">
    <Setter Property="Button.Template">
        <ControlTemplate TargetType="Button">
            <ContentPresenter x:Name="PART_ContentPresenter"
                              Content="{TemplateBinding Content}"
                              Background="{TemplateBinding Background}" />
        </ControlTemplate>
    </Setter>
</ControlTheme>
// Code #2
^Button {
    [[
        :pointerover {
            Background: Red;
        }
    ]]
}
<!-- Code #3 -->
<ControlTheme x:Key="{x:Type Button}" TargetType="Button">
    <Setter Property="Button.Template">
        <ControlTemplate TargetType="Button">
            <ContentPresenter x:Name="PART_ContentPresenter"
                              Content="{TemplateBinding Content}"
                              Background="{TemplateBinding Background}" />
        </ControlTemplate>
    </Setter>
    
    <Style Selector="^:pointerover">
        <Setter Property="Background" Value="Red"/>
    </Style>
</ControlTheme>

2. Normal Style

Normal styles are Acss styles without the "^" symbol, which are parsed as Avalonia styles and put into Styles in IAcssFile. Note that IAcssFile inherits the Avalonia interface IStyle, and IAcssFile is loaded by IAcssLoadr into the Owner of the Styles type passed in during loading.

An example of the normal style is shown below:

Button:pointerover{
    Background: red;
}

3. Logic sub-style (beta)

Logical sub-styles are not currently supported by Avalonia, they mean that the style will be placed in the Styles of the Target of the Selector of the parent style.

For example, if the Target of "/template/Grid#PART_MonthView" is a Grid, the logical child style will be placed into the Styles of the Grid as a normal child style.

Logic sub-style of the Selector before the need to add the ">" symbol, code examples:

/template/ Grid#PART_MonthView{
    [[
        >TextBlock.Week{
            VerticalAlignment:Center;
            HorizontalAlignment:Center;
            Margin:0,12;
        }
    ]]
}

Style inheritance

Unlike Avalonia where styles can only BaseOn a base style, Acss styles can't directly inherit styles, but they can inherit multiple style templates.

1. Style templates

An abstract template is a style template that does not specify a Selector. Abstract templates do not specify a specific type, so they cannot be parsed into specific Avalonia styles.

For example, the following defines two style templates with ".ctrl" and ".border" as their Key.

.ctrl{
    Foreground: var(fore);
    Background: var(ctrl-back);
}

.border{
    BorderBrush:var(ctrl-border);
    BorderThickness: 1;
}

.const-box @extend(.ctrl, .border) { }

2. File Import

Inheriting a style template requires that the style template is available in the current IAcssFile environment, which can be achieved in two ways.

  • Define the template in the current IAcssFile. Note that it must be defined at the outermost level, not in any of Style's Children.

  • Define the template in a separate file and import it at the top of the file using the base keyword. The method is as follows:

// Begin of the file.
base ./Bases/Bases.acss;
base ./Bases/Control.acss;

// ...

Note

  1. The relative directory of the imported file refers to the current IAcssFile directory. The relative directory of the imported file refers to the directory where the current IAcssFile is located.

  2. Multiple files can be imported, one line at a time, terminated by a ";" flag.

3. Inheritance templates

Acss styles can inherit from multiple templates.

/* Style.Template.acss */

// Style template for properties.
.ctrl{
    Foreground: var(fore);
    Background: var(ctrl-back);
}
.border{
    BorderBrush:var(ctrl-border);
    BorderThickness: 1;
}

// Style template for states.
.pointerover{
    [[
        :pointerover{
            Foreground: var(fore-hover);
            Background: var(ctrl-back-hover);
            BorderBrush: var(fluent-ctrl-border-hover);
        }
    ]]
}
.pressed{
    [[
        :pressed{
            Foreground: var(fore-pressed);
            Background: var(ctrl-back-pressed);
            BorderBrush: var(fluent-ctrl-border-pressed);
        }
    ]]
}

// Style Template Inheritance Template Multiple Inheritance
.const-box @extend(.ctrl, .border) { }
.box @extend(.ctrl, .border, .pointerover, .pressed) { }

Use the template:

/* TextBox.acss */

base ./Bases/Bases.acss;

.disabled{
    [[
        :disabled{
            Opacity:0.4;
        }
    ]]
 }

// Multi-inheritance
^TextBox @extend(.box, .disabled){
    // ...
}

Last updated

Was this helpful?