样式选择器语法
本页面列出了XAML样式选择器的语法,以及执行相同选择的C#代码方法。
按控件类选择
<Style Selector="Button">
<Style Selector="local|Button">
new Style(x => x.OfType<Button>());
new Style(x => x.OfType(typeof(Button)));
按控件类选择。
以上第一个示例选择Avalonia.Controls.Button
类。要在类型中包含XAML命名空间,请使用|
字符将命名空间和类型分隔。
此选择器不匹配派生类型。若要匹配派生类型,请使用:is
选择器,参见下文。
请注意,对象的类型实际上是通过查看其StyleKey
属性来确定的。默认情况下,它只返回当前实例的类型,但是,如果您希望从Button
继承的控件被视为Button
样式,则可以在您的类上重写StyleKeyOverride
属性以返回typeof(Button)
。
按名称选择
<Style Selector="#myButton">
<Style Selector="Button#myButton">
new Style(x => x.Name("myButton"));
new Style(x => x.OfType<Button>().Name("myButton"));
按Name
属性选择控件,前面加上#
(井号)字符作为前缀。
按样式类选择
<Style Selector="Button.large">
<Style Selector="Button.large.red">
new Style(x => x.OfType<Button>().Class("large"));
new Style(x => x.OfType<Button>().Class("large").Class("red"));
选择具有指定样式类或多个样式类的控件。多个类用点号分隔。如果选择器中指定了多个类,则控件必须同时拥有所有请求的类定义才能匹配。
按伪类选择
<Style Selector="Button:focus">
<Style Selector="Button.large:focus">
new Style(x => x.OfType<Button>().Class(":focus"));
new Style(x => x.OfType<Button>().Class("large").Class(":focus"));
使用当前伪类选择控件。冒号字符在选择器中定义伪类名称。选择器中只能有一个伪类。与其他类一起使用时,伪类必须是列表中的最后一个。
有关伪类的更多详细信息,请参见此处的参考。
包括派生类
<Style Selector=":is(Button)">
<Style Selector=":is(local|Button)">
new Style(x => x.Is<Button>());
new Style(x => x.Is(typeof(Button)));
这与样式类选择器非常相似,但它还匹配派生类型。
技术细节:在匹配过程中,Avalonia UI 通过检查控件的StyleKey
属性来确定其类型。
有趣的是,这允许您编写非常通用的基于类别的选择器。由于所有控件都派生自类Control
,因此只选择样式类margin2
的选择器可以编写如下:
<Style Selector=":is(Control).margin2">
<Style Selector=":is(local|Control.margin2)">
new Style(x => x.Is<Control>().Class("margin2"));
new Style(x => x.Is(typeof(Control)).Class("margin2"));
子操作符
<Style Selector="StackPanel > Button">
new Style(x => x.OfType<StackPanel>().Child().OfType<Button>());
通过使用>
字符分隔两个选择器来定义子选择器。此选择器仅匹配逻辑控件树中的直接子项。
有关逻辑控件树背后的概 念,请参见这里。
例如,将上述选择器应用于以下XAML:
<StackPanel>
<Button>Save</Button>
<DockPanel Width="300" Height="300">
<Button DockPanel.Dock="Top">Top</Button>
<TextBlock>Some text</TextBlock>
</DockPanel
</StackPanel>
该选择器将匹配第一个按钮,但不会匹配第二个按钮。这是因为第二个按钮不是堆栈面板的直接子项(它也在停靠面板中)。
任意后代操作符
<Style Selector="StackPanel Button">
new Style(x => x.OfType<StackPanel>().Descendant().OfType<Button>());
当两个选择器由空格分隔时,选择器将匹配逻辑树中的任意后代。父级在左边,后代在右边。
因此,将上述选择器应用于之前的XAML示例,两个按钮都将被选择。
按属性匹配
<Style Selector="Button[IsDefault=true]">
new Style(x => x.OfType<Button>().PropertyEquals(Button.IsDefaultProperty, true));
您可以细化选择器,以包含属性的值。属性=值对在方括号内定义。这将匹配具有指定属性设置为指定值的任何控件。
<StackPanel Orientation="Horizontal">
<Button IsDefault="True">Save</Button>
<Button>Cancel</Button>
</StackPanel>
例如,在上面的XAML中,第一个按钮将被选择,但第二个按钮不会被选择。
注意:当您将附加属性用作属性匹配时,属性名必须用括号括起来。例如:
<Style Selector="TextBlock[(Grid.Row)=0]">
进一步注意:当您使用属性匹配时,属性类型必须支持组件模型类型转换器TypeConverter
类。有关更多信息,请参阅_Microsoft_文档。
按模板选择
<Style Selector="Button /template/ ContentPresenter">
new Style(x => x.OfType<Button>().Template().OfType<ContentPresenter>());
您可以使用上述语法在控件模板中匹配控件。此处列出的所有其他选择器都适用于逻辑树,但此选择器可以进入模板。
在上面的示例中,如果按钮具有模板,则该选择器将选择模板中的内容呈现控件(类ContentPresenter
)。
Not 函数
<Style Selector="TextBlock:not(.h1)">
new Style(x => x.OfType<TextBlock>().Not(y => y.Class("h1")));
该函数否定括号中的选择。在上面的示例中,将匹配所有没有h1
类的文本块控件。
按列表选择
<Style Selector="TextBlock, Button">
new Style(x => Selectors.Or(x.OfType<TextBlock>(), x.OfType<Button>()))
您可以选择与逗号分隔的选择器列表匹配的任何元素。样式中的任何setter必须更改对所有项目都通用的属性。
按子元素位置公式选择
<Style Selector="TextBlock:nth-child(2n+3)">
new Style(x => x.OfType<TextBlock>().NthChild(2, 3));
您可以根据元素在相邻组内的位置进行匹配。这与父(容器)控件的类别无关。
选择是基于样式中的简单公式An + B
,以便 A
控制步长,B
控制从开始位置的偏移。在nth-child公式(上面)中,将 n
作为零提供给公式,以及从零开始的所有正整数,并且与子元素的基于一的位置的结果进行比较。
因此,对于上面的选择器:
Child = 1 | Child = 2 | Child = 3 | Child = 4 |
---|---|---|---|
n=0, n=1 | n=0, n=1 | n=0, n=1 | n=0, n=1 |
3, 5 | 3, 5 | 3, 5 | 3, 5 |
不匹配 | 不匹配 | 匹配 | 不匹配 |
如果公式计算结果小于1,则忽略它——从不会有任何具有该索引的子元素。
有一个与从组的末尾计数的公式相对应的选择器:
<Style Selector="TextBlock:nth-last-child(2n+3)">
new Style(x => x.OfType<TextBlock>().NthLastChild(2, 3));