在Xamarin.Forms中,公共语言运行库(CLR)属性的功能通过可绑定属性进行扩展。 可绑定属性是特殊类型的属性,属性的值由Xamarin.Forms属性系统跟踪。 本文介绍了可绑定属性,并演示了如何创建和使用它们。
概观
可绑定属性通过使用BindableProperty类型来支持属性来扩展CLR属性功能,而不是使用字段来支持属性。 可绑定属性的目的是提供一个支持通过父子关系设置的数据绑定,样式,模板和值的属性系统。 另外,可绑定属性可以提供默认值,属性值验证以及监视属性更改的回调。
属性应该作为可绑定属性来实现,以支持以下一个或多个功能:
-
充当数据绑定的有效目标属性。
-
通过样式设置属性。
-
提供与属性类型的默认属性值不同的默认属性值。
-
验证属性的值。
-
监视属性更改。
Xamarin.Forms可绑定属性的示例包括Label.Text,Button.BorderRadius和StackLayout.Orientation。 每个可绑定属性都有一个类型为BindableProperty的相应公共静态只读属性,它暴露在相同的类上,并且是可绑定属性的标识符。 例如,Label.Text属性的相应可绑定属性标识符是Label.TextProperty。
创建和使用可绑定的属性
创建可绑定属性的过程如下所示:
-
使用BindableProperty.Create方法重载之一创建一个BindableProperty实例。
-
定义BindableProperty实例的属性访问器。
请注意,必须在UI线程上创建所有BindableProperty实例。 这意味着只有在UI线程上运行的代码才能获取或设置可绑定属性的值。 但是,通过使用Device.BeginInvokeOnMainThread方法封送到UI线程,可以从其他线程访问BindableProperty实例。
创建一个属性
为了创建一个BindableProperty实例,包含的类必须从BindableObject类派生。 但是,BindableObject类在类层次结构中很高,所以用于用户界面功能的大多数类都支持可绑定属性。
可以通过声明BindableProperty类型的公共静态只读属性来创建可绑定属性。 应将bindable属性设置为BindableProperty.Create方法重载之一的返回值。 声明应该位于BindableObject派生类的主体内,但不在任何成员定义之内。
创建BindableProperty时必须至少指定一个标识符以及以下参数:
-
BindableProperty的名称。
-
属性的类型。
-
拥有对象的类型。
-
属性的默认值。 这可以确保该属性在未设置时始终返回特定的默认值,并且可以与该属性类型的默认值不同。 在可绑定属性上调用ClearValue方法时,将恢复默认值。
以下代码显示了一个可绑定属性的示例,其中包含四个必需参数的标识符和值:
-
public static readonly BindableProperty EventNameProperty =
-
BindableProperty.Create ("EventName", typeof(string), typeof(EventToCommandBehavior), null);
这将创建一个名为EventName的BindableProperty实例,类型为string。 该属性由EventToCommandBehavior类所有,并具有默认值null。 可绑定属性的命名约定是,可绑定属性标识符必须与Create方法中指定的属性名称匹配,并附加“Property”。 因此,在上面的例子中,可绑定的属性标识符是EventNameProperty。
或者,在创建BindableProperty实例时,可以指定以下参数:
-
绑定模式。 这用于指定属性值更改传播的方向。 在默认绑定模式下,更改将从源传播到目标。
-
将在设置属性值时调用的验证委托。 有关更多信息,请参阅验证回调。
-
一个属性改变了委托,当属性值改变时将被调用。 有关更多信息,请参阅检测属性更改。
-
属性更改委托,将在属性值更改时调用。 该委托具有与更改委托的属性相同的签名。
-
强制值委托,将在属性值更改时调用。 有关更多信息,请参阅Coerce值回调。
-
用于初始化默认属性值的Func。 有关更多信息,请参阅使用Func创建默认值。
创建访问器
属性访问器是必需的,才能使用属性语法来访问可绑定属性。 Get访问器应该返回包含在相应的可绑定属性中的值。 这可以通过调用GetValue方法,传入可获取值的可绑定属性标识符,然后将结果转换为所需的类型来实现。 Set访问器应该设置相应的可绑定属性的值。 这可以通过调用SetValue方法,传入要设置值的可绑定属性标识符以及要设置的值来实现。
以下代码示例显示了EventName可绑定属性的访问者:
-
public string EventName {
-
get { return (string)GetValue (EventNameProperty); }
-
set { SetValue (EventNameProperty, value); }
-
}
使用Bindable属性
一旦创建了可绑定属性,就可以从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参数,可以使用可绑定属性注册静态属性更改的回调方法。 指定的回调方法将在可绑定属性的值更改时调用。
下面的代码示例显示了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参数用于表示拥有的类的哪个实例已经报告了更改,并且这两个对象参数的值表示可绑定属性的旧值和新值。
验证回调
通过为BindableProperty.Create方法指定validateValue参数,可以向可绑定属性注册静态验证回调方法。 当设置了可绑定属性的值时,将调用指定的回调方法。
以下代码示例显示了Angle bindable属性如何将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参数,可以使用可绑定属性注册静态胁迫值回调方法。 指定的回调方法将在可绑定属性的值更改时调用。
Coerce值回调用于在属性值发生更改时强制对可绑定属性进行重新评估。 例如,可以使用胁迫值回调来确保一个可绑定属性的值不大于另一个可绑定属性的值。
下面的代码示例显示角度bindable属性如何将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);
-
...
-
-
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;
-
}
CoerceAngle方法将检查MaximumAngle属性的值,如果Angle属性值大于此值,则会将值强制为MaximumAngle属性值。
用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参数设置为调用Device.GetNamedSize方法的Func,以返回一个double,该double表示在本机平台上的Label上使用的字体的命名大小。
概要
本文提供了可绑定属性的介绍,并演示了如何创建和使用它们。 可绑定属性是特殊类型的属性,属性的值由Xamarin.Forms属性系统跟踪。