摘要:第 11 章. 可绑定的基础结构
注意
本书于 2016 年春季出版,之后再未更新。 书中有许多内容仍然有价值,但有些内容已过时,有些主题不再完全正确或完整。
每个 C# 程序员都熟悉 C# 属性。 属性包含 set 访问器和/或 get 访问器。 它们通常称为公共语言运行时的 CLR 属性。
Xamarin.Forms 定义了一个增强属性定义,称为“可绑定属性”,由 BindableProperty
类封装,并由 BindableObject
类提供支持。 这些类是相关的,但非常不同:BindableProperty
用于定义属性本身;BindableObject
与 object
相似,因为它是定义可绑定属性的类的基类。
Xamarin.Forms 类层次结构
ClassHierarchy 示例使用反射来显示 Xamarin.Forms 的类层次结构,并演示 BindableObject
在此层次结构中发挥的重要作用。 BindableObject
派生自 Object
,是 Element
的父类,VisualElement
派生自该父类。 这是 Page
和 View
的父类,后者是 Layout
的父类:
查看 BindableObject 和 BindableProperty
在从 BindableObject
派生的类中,许多 CLR 属性被称为“受支持的”可绑定属性。 例如,Label
类的 Text
属性是 CLR 属性,但是 Label
类还定义了类型为 BindableProperty
的名为 TextProperty
的公共静态只读字段。
应用程序可以正常设置或获取 Label
的 Text
属性,或者应用程序可以通过使用 Label.TextProperty
参数调用 BindableObject
定义的 SetValue
方法来设置 Text
。 同样,应用程序可以通过再次使用 Label.TextProperty
参数调用 GetValue
方法来获取 Text
属性的值。 PropertySettings 示例对此进行了演示。
实际上,Text
CLR 属性完全是使用由 BindableObject
以及 Label.TextProperty
静态属性一起定义的 SetValue
和 GetValue
方法实现的。
BindableObject
和 BindableProperty
为以下操作提供支持:
- 提供属性默认值
- 存储其当前值
- 提供验证属性值的机制
- 保持单个类中相关属性之间的一致性
- 响应属性变化
- 在属性即将更改或已更改时触发通知
- 支持数据绑定
- 支持样式
- 支持动态资源
每当由可绑定属性提供支持的属性发生更改时,BindableObject
就会触发 PropertyChanged
事件,以标识已更改的属性。 当属性设置为相同值时,不会触发此事件。
某些属性不受可绑定属性支持,而某些 Xamarin.Forms 类(例如 Span
)不是从 BindableObject
派生的。 只有从 BindableObject
派生的类才能支持可绑定属性,因为 BindableObject
定义了 SetValue
和 GetValue
方法。
因为 Span
不是从 BindableObject
派生的,所以它的任何属性(例如 Text
)都不受可绑定属性的支持。 这就是上一章的 DynamicVsStatic 示例中,Span
的 Text
属性上的 DynamicResource
设置引发异常的原因。 DynamicVsStaticCode 示例演示如何使用 Element
定义的 SetDynamicResource
方法在代码中设置动态资源。 第一个参数是类型为 BindableProperty
的对象。
同样,BindableObject
定义的 SetBinding
方法具有类型为 BindableProperty
的第一个参数。
定义可绑定属性
可以使用静态 BindableProperty.Create
方法定义自己的可绑定属性,以创建类型为 BindableProperty
的静态只读字段。
Xamarin.FormsBook.Toolkit 库中的 AltLabel
类对此进行了演示。 该类派生自 Label
,可让用户指定字号(以磅为单位)。 PointSizedText 示例对此进行了演示。
BindableProperty.Create
方法需要四个参数:
propertyName
:属性的文本名称(与 CLR 属性名称相同)returnType
:CLR 属性的类型declaringType
:声明属性的类的类型defaultValue
:属性的默认值
由于 defaultValue
的类型为 object
,因此编译器必须能够确定默认值的类型。 例如,如果 returnType
为 double
,则应将 defaultValue
设置为类似于 0.0 的值,而不是仅设置为 0,否则类型不匹配将在运行时触发异常。
可绑定属性通常还包括:
propertyChanged
:属性更改值时调用的静态方法。 第一个参数是属性已更改的类的实例。
BindableProperty.Create
的其他参数并不常见:
defaultBindingMode
:与数据绑定结合使用(如以下章节中所述:第 16 章数据绑定)validateValue
:用于检查有效值的回叫propertyChanging
:一个回叫,指示何时要更改属性coerceValue
:一个回叫,将设定值强制转换为另一个值defaultValueCreate
:一个回叫,创建无法在类(例如,集合)的实例之间共享的默认值
只读可绑定属性
可绑定属性可以是只读的。 创建只读可绑定属性需要调用静态方法 BindableProperty.CreateReadOnly
来定义类型为 BindablePropertyKey
的专用静态只读字段。
然后,将 CLR 属性 set
访问器定义为 private
,以使用 BindablePropertyKey
对象调用 SetValue
重载。 这样可以防止在类外部设置属性。
BaskervillesCount 示例中使用的 CountedLabel
类对此进行了演示。