样式语法
样式的基本语法如下:
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 {
// ...
}
]]
}
特别注意
Acss 的 Children 必须放在样式的最后,其后的 Setter 将不会生效。
Selector 语法
Acss 的样式选择器(Selector)的语法和 Avalonia 中完全一致。唯一区别在于子样式的 Selector 前面不需要添加 “^” 符号。
Setter 语法
Setter 放在样式当中的形式前面已经进行了展示。这里单独说明下其他特征。
Setter 中的冒号 “:” 前后的空白字符不会影响语句效果。
Setter 的结束符 “;” 是必不可少的,但是集合属性不需要,或者最后一个 Setter 可省略。
Setter 的 Property 是大小写敏感的。
Setter 的 Value 的解析和资源值解析语法一致。
Setter 的 Value 可以使用静态实例,使用 “@” 符号标记静态类型,后直接访问静态属性,例如:
// ...
TextDecorations: @TextDecorations.Strikethrough;
// ...
需要注意的是,只有在类型解析服务当中注册过的类型,才能被访问。
例如上述代码中的 TextDecorations 在 Acss 内置的类型解析器当中被注册,你可以直接使用。
Setter 的 集合类型的值定义有特殊的语法。例如对于 Transitions 属性,它是一个集合 。
// 定义了三个 Transition 的集合对象 Transitions,将其赋值给 Transitions 属性。
// 其中,第一个是直接定义的 Transition,第二第三个是访问的动态资源。
Transitions:[
RenderTransform 0.075 0 LinearEasing;
var(stRenderTransform);
var(stBorderBrush);
]
目前除了 Transitions,暂时没有支持其他集合类型的属性。后续会考虑增加支持。
样式的分类
Acss 的样式最终还是会生成 Avalonia 样式来产生效果。但是逻辑上我们仍然给它进行了分类。
1. 主题子样式
主题子样式是针对某个类型的 Control 定义的子样式,其样式解析成 Avalonia 样式后,会在当前环境和 Application 范围内查找该类型 Control 的 ControlTheme,并将样式加入到该 ControlTheme 当中作为子样式存在。
这和你直接在 ControlTheme 中定义子样式别无二致。
主题子样式的 Selector 前需要加上 “^” 符号,它表示该样式是主题子样式,而非普通样式。
特别注意
“^” 符号表示主题子样式,这和 Avalonia 中它的用法并不相同。Avalonia 中它表示嵌套子样式。
如下三段代码中,在实际效果上,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>
生效范围
从概念上和实际效果来说,主题子样式的生效范围在于第一个被搜索到的 ControlTheme 所能应用的范围,而不是该样式所在的 Acss 文件所能应用的范围。
2. 普通样式
普通样式则是不带 “^” 符号的 Acss 样式,它会被解析为 Avalonia 样式后,放入 IAcssFile 的 Styles 当中。注意,IAcssFile 继承了 Avalonia 接口 IStyle。而 IAcssFile 则是在被 IAcssLoadr 加载时,放入加载时传入的 Styles 类型的 Owner 当中。
生效范围
普通样式的生效范围则是 IAcssFile 的生效范围,IAcssFile 的生效范围则是其 Owner 的生效范围。
普通样式的示例如下:
Button:pointerover{
Background: red;
}
3. 逻辑子样式(beta)
逻辑子样式不属于 Avalonia 现有支持的功能,它指的是,该样式将会被放入父样式的 Selector 的 Target 的 Styles 当中。
例如,“/template/Grid#PART_MonthView” 的 Target 是 Grid,逻辑子样式将会被放入 Grid 的 Styles 当中,作为普通的子样式存在。
特别注意
逻辑子样式目前属于实验功能,暂不稳定,不推荐使用。
逻辑子样式的 Selector 前需添加 “>” 符号,代码示例:
/template/ Grid#PART_MonthView{
[[
>TextBlock.Week{
VerticalAlignment:Center;
HorizontalAlignment:Center;
Margin:0,12;
}
]]
}
样式继承
不同于 Avalonia 中样式只能 BaseOn 一个基样式,Acss 的样式不能直接继承样式,但是可以继承多个样式模板。
1. 样式模板
抽象模板指的是,不指定 Selector 的样式模板。抽象模板没有指定具体的类型,因此它也不能被解析成具体的 Avalonia 样式。
例如,下面定义了两个样式模板,模板的 Key 分别为 “.ctrl” 和 “.border”。
.ctrl{
Foreground: var(fore);
Background: var(ctrl-back);
}
.border{
BorderBrush:var(ctrl-border);
BorderThickness: 1;
}
.const-box @extend(.ctrl, .border) { }
2. 文件导入
继承样式模板的条件是,当前 IAcssFile 环境中,具备该样式模板,有两种方式可以达到目的。
在当前 IAcssFile 中定义该模板。注意须定义在最外层,而不能放入任何 Style 的 Children 当中。
在独立的文件当中定义该模板,使用 base
关键字在文件最前面导入该文件。方法如下:
// Begin of the file.
base ./Bases/Bases.acss;
base ./Bases/Control.acss;
// ...
3. 继承模板
Acss 的样式可以继承多个模板。
/* 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);
}
]]
}
// 样式模板继承模板多继承
.const-box @extend(.ctrl, .border) { }
.box @extend(.ctrl, .border, .pointerover, .pressed) { }
使用模板:
/* TextBox.acss */
base ./Bases/Bases.acss;
.disabled{
[[
:disabled{
Opacity:0.4;
}
]]
}
// 多继承
^TextBox @extend(.box, .disabled){
// ...
}