设置器优先级
Avalonia 的 Setter
按照 BindingPriority
、视觉树局部性和样式集合顺序依次应用。每个 StyledProperty
都单独应用优先级,从而使得样式可以受益于组合。DirectProperty
和 CLR 属性不能被样式化,因此不参与此优先级。
绑定优先级
Animation = -1, // 最高优先级
LocalValue = 0,
StyleTrigger,
Template,
Style,
Inherited,
Unset = int.MaxValue, // 最低优先级
如何在XAML中分配绑定优先级?
BindingPriority
不能在 XAML 中显式设置。以下示例展示了如何在每个场景中隐式分配 绑定优先级
。这对于设计和排除样式故障至关重要,以确保样式按预期工作。
Animation
Animation
具有最高的 绑定优先级
,并应用于 Keyframe
中的 Setter
,通常在整个过渡系统中应用。
<Button Background="Green" Content="Bounces from Red to Blue">
<Button.Styles>
<Style Selector="Button">
<Style.Animations>
<Animation IterationCount="Infinite" Duration="0:0:2">
<KeyFrame Cue="0%">
<Setter Property="Background" Value="Red" />
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Background" Value="Blue" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</Button.Styles>
</Button>
LocalValue
当 XAML 属性在 ControlTemplate
之外直接设置时分配。下面的两个 Background
Setter
都将具有 LocalValue
优先级。
<Button Background="Orange" />
<Button Background="{DynamicResource ButtonBrush}" />
资源标记扩展对优先级没有任何影响。
StyleTrigger
当 Selector
具有条件激活时,Setter
的 绑定优先级
从 Style
提升到 StyleTrigger
。任何具有条件激活的两个选择器将具有相同的优先级,无论存在多少激活器以及激活器在选择器语法中的位置。Avalonia 没有 CSS 的 Specificity 概念。
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Orange" />
</Style>
样式类、伪类、子位置和属性匹配选择器是条件性的。控件名称选择器不是条件性的。
Template
当属性在 ControlTemplate
中直接设置时。下面的 BorderThickness
、Background
和 Padding
具有 Template
优先级。
<ControlTemplate>
<Border BorderThickness="2">
<Button Background="{DynamicResource ButtonBrush}" Padding="{TemplateBinding Padding}" />
</Border>
</ControlTemplate>
Style
当 Setter
在 Style
中定义且没有条件激活时。
<Style Selector="Button /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Orange" />
</Style>
特别值得注意的是,其优先级低于 Template
。因此,这些选择器不能用于覆盖上述 Template
示例中提到的属性。
Inherited
当属性未设置时,它可能会从其父级继承属性值。这必须在属性注册期间或在 OverrideMetadata
中指定。
public static readonly StyledProperty<bool> UseLayoutRoundingProperty =
AvaloniaProperty.Register<Layoutable, bool>(
nameof(UseLayoutRounding),
defaultValue: true,
inherits: true);