Xamarin.Forms 可绑定属性
可绑定属性通过使用 BindableProperty
类型支持属性,而不是使用字段支持属性,扩展了 CLR 属性功能。 可绑定属性的目的是提供一个属性系统,它支持通过父子关系设置的数据绑定、样式、模板和值。 此外,可绑定属性可以提供默认值、属性值验证以及监控属性更改的回调。
属性应作为可绑定属性实现,以支持以下一个或多个功能:
- 充当数据绑定的有效目标属性。
- 通过样式设置属性。
- 提供与属性类型的默认值不同的默认属性值。
- 验证属性的值。
- 监控属性更改。
Xamarin.Forms 可绑定属性的示例包括 Label.Text
、Button.BorderRadius
和 StackLayout.Orientation
。 每个可绑定属性都有一个在相同类上公开的相应 public static readonly
类型的 BindableProperty
字段,该字段是可绑定属性的标识符。 例如,Label.Text
属性的相应可绑定属性标识符为 Label.TextProperty
。
创建可绑定属性
创建可绑定属性的过程如下所示:
- 使用其中一个
BindableProperty.Create
方法重载创建BindableProperty
实例。 - 定义
BindableProperty
实例的属性访问器。
必须在 UI 线程上创建所有 BindableProperty
实例。 这意味着,只有 UI 线程上运行的代码才能获取或设置可绑定属性的值。 但是,可以通过使用 Device.BeginInvokeOnMainThread
方法封送到 UI 线程,从其他线程访问 BindableProperty
实例。
创建属性
若要创建 BindableProperty
实例,包含类必须派生自 BindableObject
类。 不过,BindableObject
类在类层次结构中的位置较高,因此大多数用于用户界面功能的类都支持可绑定属性。
可以通过声明 BindableProperty
类型的 public static readonly
属性来创建可绑定属性。 可绑定属性应设置为 BindableProperty.Create
方法重载之一的返回值。 声明应位于 BindableObject
派生类的正文中,但不属于任何成员定义。
创建 BindableProperty
时,必须至少指定一个标识符以及以下参数:
BindableProperty
的名称。- 属性类型。
- 所属对象的类型。
- 属性的默认值。 这可以确保属性在未设置时始终返回特定的默认值,并且它可以与该属性类型的默认值不同。 在可绑定属性上调用
ClearValue
方法时,将还原默认值。
重要
可绑定属性的命名约定是,可绑定属性标识符必须与 Create
方法中指定的属性名称匹配,并将“属性”追加到该方法中。
以下代码展示了可绑定属性的示例,其中包含四个必需参数的标识符和值:
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create ("EventName", typeof(string), typeof(EventToCommandBehavior), null);
这将创建名为 EventNameProperty
的 BindableProperty
实例,类型为 string
。 此属性归 EventToCommandBehavior
类所有,其默认值为 null
。
创建 BindableProperty
实例时,也可以选择指定以下参数:
- 绑定模式。 这用于指定属性值更改的传播方向。 在默认绑定模式下,更改将从源传播到目标。
- 设置属性值时将调用的验证委托。 有关详细信息,请参阅验证回调。
- 属性值发生更改时将调用的属性已更改委托。 有关详细信息,请参阅检测属性更改。
- 属性值即将更改时将调用的属性即将更改委托。 此委托与属性更改的委托具有相同的签名。
- 属性值发生更改时将调用的强制值委托。 有关详细信息,请参阅强制值回调。
- 用于初始化默认属性值的
Func
。 有关详细信息,请参阅使用 Func 创建默认值。
创建访问器
属性访问器需要使用属性语法才能访问可绑定属性。 Get
访问器应返回相应可绑定属性中包含的值。 可以通过调用 GetValue
方法,传入要获取值的可绑定属性标识符,然后将结果强制转换为所需的类型来达成此目的。 Set
访问器应设置相应可绑定属性的值。 可以通过调用 SetValue
方法、传入要设置值的可绑定属性标识符和要设置的值达成此目的。
以下代码示例演示 EventName
可绑定属性的访问器:
public string EventName
{
get { return (string)GetValue (EventNameProperty); }
set { SetValue (EventNameProperty, value); }
}
使用可绑定属性
创建可绑定属性后,可以从 XAML 或代码使用它。 在 XAML 中,可通过声明带有前缀的命名空间、指示 CLR 命名空间名称的命名空间声明,以及(可选)程序集名称来达成此目的。 有关详细信息,请参阅 XAML 命名空间。
以下代码示例演示包含可绑定属性的自定义类型的 XAML 命名空间,该属性在与引用自定义类型的应用程序代码相同的程序集中定义:
<ContentPage ... xmlns:local="clr-namespace:EventToCommandBehavior" ...>
...
</ContentPage>
设置 EventName
可绑定属性时将使用命名空间声明,如以下 XAML 代码示例所示:
<ListView ...>
<ListView.Behaviors>
<local:EventToCommandBehavior EventName="ItemSelected" ... />
</ListView.Behaviors>
</ListView>
以下代码示例显示相应的 C# 代码:
var listView = new ListView ();
listView.Behaviors.Add (new EventToCommandBehavior
{
EventName = "ItemSelected",
...
});
高级方案
创建 BindableProperty
实例时,可以设置许多可选参数来启用高级可绑定属性应用场景。 本部分将探讨这些应用场景。
检测属性更改
可通过为 BindableProperty.Create
方法指定 propertyChanged
参数,向可绑定属性注册 static
属性更改的回调方法。 当可绑定属性的值更改时,将调用指定的回叫方法。
以下代码示例演示 EventName
可绑定属性如何将 OnEventNameChanged
方法注册为属性更改的回调方法:
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create (
"EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged);
...
static void OnEventNameChanged (BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
}
在属性更改的回调方法中,BindableObject
参数用于表示所属类的哪个实例报告了更改,两个 object
参数的值分别表示可绑定属性的新旧值。
验证回调
可通过为 BindableProperty.Create
方法指定 validateValue
参数,通过可绑定属性注册 static
验证回调方法。 设置可绑定属性的值时,将调用指定的回调方法。
以下代码示例演示 Angle
可绑定属性如何将 IsValidValue
方法注册为验证回调方法:
public static readonly BindableProperty AngleProperty =
BindableProperty.Create ("Angle", typeof(double), typeof(HomePage), 0.0, validateValue: IsValidValue);
...
static bool IsValidValue (BindableObject view, object value)
{
double result;
bool isDouble = double.TryParse (value.ToString (), out result);
return (result >= 0 && result <= 360);
}
验证回调随值一起提供,如果该值对属性有效,则应返回 true
,否则返回 false
。 如果验证回叫返回 false
(应由开发人员处理),则会引发异常。 验证回调方法的典型用法是在设置可绑定属性时约束整数值或双精度值。 例如,IsValidValue
方法将检查属性值是否为介于 0 到 360 范围之间的 double
。
强制值回调
可通过为 BindableProperty.Create
方法指定 coerceValue
参数,向可绑定属性注册 static
强制值回调方法。 当可绑定属性的值更改时,将调用指定的回叫方法。
重要
BindableObject
类型包含 CoerceValue
方法,可以通过调用其强制值回调来强制重新计算其 BindableProperty
参数的值。
强制值回叫用于在属性值更改时强制重新计算可绑定属性。 例如,可使用强制值回调确保一个可绑定属性的值不大于另一个可绑定属性的值。
以下代码示例演示 Angle
可绑定属性如何将 CoerceAngle
方法注册为强制值回调方法:
public static readonly BindableProperty AngleProperty = BindableProperty.Create (
"Angle", typeof(double), typeof(HomePage), 0.0, coerceValue: CoerceAngle);
public static readonly BindableProperty MaximumAngleProperty = BindableProperty.Create (
"MaximumAngle", typeof(double), typeof(HomePage), 360.0, propertyChanged: ForceCoerceValue);
...
static object CoerceAngle (BindableObject bindable, object value)
{
var homePage = bindable as HomePage;
double input = (double)value;
if (input > homePage.MaximumAngle)
{
input = homePage.MaximumAngle;
}
return input;
}
static void ForceCoerceValue(BindableObject bindable, object oldValue, object newValue)
{
bindable.CoerceValue(AngleProperty);
}
CoerceAngle
方法检查 MaximumAngle
属性的值,并且如果 Angle
属性值大于该值,则将该值强制转换为 MaximumAngle
属性值。 此外,当 MaximumAngle
属性更改时,通过调用 CoerceValue
方法,对 Angle
属性调用强制值回调。
使用 Func 创建默认值
Func
可用于初始化可绑定属性的默认值,如以下代码示例所示:
public static readonly BindableProperty SizeProperty =
BindableProperty.Create ("Size", typeof(double), typeof(HomePage), 0.0,
defaultValueCreator: bindable => Device.GetNamedSize (NamedSize.Large, (Label)bindable));
defaultValueCreator
参数设置为 Func
,它调用 Device.GetNamedSize
方法来返回 double
,表示在本机平台上用于 Label
的字体的命名大小。