定义属性
如果你正在创建一个控件,你会想要在你的控件上定义属性。你可以通过定义 AvaloniaProperty
来实现。Avalonia 属性由两部分组成:属性定义和属性的 CLR Getter/Setter。
注册样式属性
除非你有充分的理由不这样做,否则你应该将控件上的属性定义为 样式属性。样式属性能够确保你的属性能够与 Avalonia 的样式系统正确地工作。
你可以通过调用 AvaloniaProperty.Register
来注册一个样式属性,并将结果存储在一个 static readonly
字段中。然后,你需要创建一个标准的 C# 属性来访问它。
以下是 Border
控件如何定义它的 Background
属性的代码:
AvaloniaProperty.Register
方法还接受一些其他参数:
defaultValue
: 这为属性设置了默认值。请确保只在此处传递值类型和不可变类型,因为传递引用类型将导致同一对象在注册属性的所有实例上使用。inherits
: 指定该属性的默认值是否应该来自于父控件。defaultBindingMode
: 属性的默认绑定模式。可以设置为OneWay
、TwoWay
、OneTime
或OneWayToSource
。validate
: 一种类型为Func<TOwner, TValue, TValue>
的验证/强制转换函数。该函数接受正在设置该属性的类的实例以及该值,并返回强制转换后的值,或针对无效值抛出异常。
样式属性类似于其他 XAML 框架中的
DependencyProperty
。
属性的命名约定及其后备的 AvaloniaProperty 字段的命名是重要的。该字段的名称始终为该属性的名称,附加了后缀
Property
。
在其他类中使用 StyledProperty
StyledProperty
有时,你想要添加到你的控件中的属性已经存在于其他控件中,比如 Background
。为了在注册在另一个控件上定义的属性时,你需要调用 StyledProperty.AddOwner
:
注意:与 WPF/UWP 不同,必须在类上注册属性,否则它不能在该类的对象上设置。但这在未来可能会改变。
只读属性
要创建只读属性,可以使用 AvaloniaProperty.RegisterDirect
方法。以下是 Visual
注册只读 Bounds
属性的方法:
可以看到,只读属性被存储为对象上的字段。在注册属性时,传递了一个 getter,该 getter 通过 GetValue
访问属性值,然后使用 SetAndRaise
通知监听器有关属性更改的情况。
附加属性
附加属性 与样式属性几乎相同,只是它们是使用 RegisterAttached
方法注册的,并且它们的访问器被定义为静态方法。
下面是 Grid
定义其 Grid.Column
附加属性的方法:
直接 AvaloniaProperties
正如其名称所示,RegisterDirect
不仅用于注册只读属性。您还可以将 setter 传递给 RegisterDirect
,将标准 C# 属性公开为 Avalonia 属性。
使用 AvaloniaProperty.Register
注册的 StyledProperty
维护了一个优先级列表,该列表允许样式工作。但是,这对于许多属性来说太过复杂,例如 ItemsControl.Items
- 这将永远不会被样式化,样式属性的开销是不必要的。
下面是 ItemsControl.Items
的注册方法:
直接属性是样式属性的轻量级版本,支持以下功能:
AvaloniaObject.GetValue
AvaloniaObject.SetValue(仅适用于非只读属性)
PropertyChanged
Binding(仅使用 LocalValue 优先级)
GetObservable
AddOwner
元数据
它们不支持以下功能:
验证/强制(尽管可以在属性设置器中执行此操作)
覆盖默认值。
继承的值
在另一个类上使用 DirectProperty
与样式属性一样,您也可以在 DirectProperty 上调用 AddOwner
方法将其添加到另一个类中。因为直接属性引用控件上的字段,所以您还必须为该属性添加一个字段:
何时使用 DirectProperty 和 StyledProperty
通常情况下,您应该将属性声明为样式属性。但是,直接属性有其优缺点:
优点:
对于每个实例,不需要为该属性分配额外的对象
属性 getter 是标准的 C# 属性 getter
属性 setter 是标准的 C# 属性 setter,可以引发事件。
您可以添加数据验证支持
缺点:
无法从父控件继承值
无法利用 Avalonia 的样式系统
属性值是字段,因此无论该属性是否在对象上设置,都会被分配
因此,在具有以下要求的情况下使用直接属性:
属性不需要进行样式化
属性通常或始终具有值
数据验证支持
如果您想允许属性验证数据并显示验证错误消息,则该属性必须作为 DirectProperty
实现,并且必须启用验证支持(enableDataValidation: true
)。
具有启用了数据验证的属性的示例
如果要 重用另一个类的直接属性,也可以启用数据验证。在这种情况下,请使用 AddOwnerWithDataValidation
。
示例:TextBox.TextProperty 属性重用 TextBlock.TextProperty,但添加了验证支持
Last updated