Xamarin. Forms 可系結屬性Xamarin.Forms Bindable Properties

下載範例 下載範例Download Sample Download the sample

可系結屬性會藉由支援具有BindableProperty類型的屬性來擴充 CLR 屬性功能,而不是以欄位來支援屬性。Bindable properties extend CLR property functionality by backing a property with a BindableProperty type, instead of backing a property with a field. 可系結屬性的目的是要提供支援資料系結、樣式、範本,以及透過父子式關聯性所設定之值的屬性系統。The purpose of bindable properties is to provide a property system that supports data binding, styles, templates, and values set through parent-child relationships. 此外,可系結屬性可以提供預設值、屬性值的驗證,以及監視屬性變更的回呼。In addition, bindable properties can provide default values, validation of property values, and callbacks that monitor property changes.

屬性應該實作為可系結屬性,以支援下列一或多項功能:Properties should be implemented as bindable properties to support one or more of the following features:

  • 作為資料系結的有效目標屬性。Acting as a valid target property for data binding.
  • 透過樣式設定屬性。Setting the property through a style.
  • 提供預設屬性值,其與屬性類型的預設值不同。Providing a default property value that's different from the default for the type of the property.
  • 驗證屬性的值。Validating the value of the property.
  • 監視屬性變更。Monitoring property changes.

Xamarin. Forms 可系結屬性的範例包括Label.TextButton.BorderRadiusStackLayout.OrientationExamples of Xamarin.Forms bindable properties include Label.Text, Button.BorderRadius, and StackLayout.Orientation. 每個可系結的屬性都有一個類型BindableProperty的對應 public static readonly 屬性,該類別會在相同的類別上公開,而這是可系結屬性的識別碼。Each bindable property has a corresponding public static readonly property of type BindableProperty that is exposed on the same class and that is the identifier of the bindable property. 例如,Label.Text 屬性的對應可系結屬性識別碼為Label.TextPropertyFor example, the corresponding bindable property identifier for the Label.Text property is Label.TextProperty.

建立可系結屬性Create a bindable property

建立可系結屬性的流程如下所示:The process for creating a bindable property is as follows:

  1. 使用其中一個BindableProperty.Create方法多載來建立BindableProperty實例。Create a BindableProperty instance with one of the BindableProperty.Create method overloads.
  2. 定義BindableProperty實例的屬性存取子。Define property accessors for the BindableProperty instance.

所有BindableProperty實例都必須在 UI 執行緒上建立。All BindableProperty instances must be created on the UI thread. 這表示只有在 UI 執行緒上執行的程式碼可以取得或設定可系結屬性的值。This means that only code that runs on the UI thread can get or set the value of a bindable property. 不過,您可以使用Device.BeginInvokeOnMainThread方法封送處理至 UI 執行緒,以從其他執行緒存取 BindableProperty 實例。However, BindableProperty instances can be accessed from other threads by marshaling to the UI thread with the Device.BeginInvokeOnMainThread method.

建立屬性Create a property

若要建立 BindableProperty 實例,包含的類別必須衍生自BindableObject類別。To create a BindableProperty instance, the containing class must derive from the BindableObject class. 不過,在類別階層中,BindableObject 類別很高,所以用於使用者介面功能的大部分類別都支援可系結的屬性。However, the BindableObject class is high in the class hierarchy, so the majority of classes used for user interface functionality support bindable properties.

您可以宣告BindableProperty類型的 public static readonly 屬性來建立可系結的屬性。A bindable property can be created by declaring a public static readonly property of type BindableProperty. 可系結屬性應設定為其中一個BindableProperty.Create方法多載的傳回值。The bindable property should be set to the returned value of one of the BindableProperty.Create method overloads. 宣告應位於BindableObject衍生類別的主體內,但不應位於任何成員定義的外部。The declaration should be within the body of BindableObject derived class, but outside of any member definitions.

建立BindableProperty時,至少必須指定識別碼,以及下列參數:At a minimum, an identifier must be specified when creating a BindableProperty, along with the following parameters:

  • BindableProperty的名稱。The name of the BindableProperty.
  • 屬性的類型。The type of the property.
  • 擁有物件的型別。The type of the owning object.
  • 屬性的預設值。The default value for the property. 這可確保屬性一律會在未設定時傳回特定的預設值,而且它可以與屬性類型的預設值不同。This ensures that the property always returns a particular default value when it is unset, and it can be different from the default value for the type of the property. 在可系結屬性上呼叫ClearValue方法時,將會還原預設值。The default value will be restored when the ClearValue method is called on the bindable property.

下列程式碼顯示可系結屬性的範例,其中包含四個必要參數的識別碼和值:The following code shows an example of a bindable property, with an identifier and values for the four required parameters:

public static readonly BindableProperty EventNameProperty =
  BindableProperty.Create ("EventName", typeof(string), typeof(EventToCommandBehavior), null);

這會建立一個名為 EventNameBindableProperty實例,其類型為 stringThis creates a BindableProperty instance named EventName, of type string. 屬性是由 EventToCommandBehavior 類別所擁有,且預設值為 nullThe property is owned by the EventToCommandBehavior class, and has a default value of null. 可系結屬性的命名慣例是可系結屬性識別碼必須符合在 Create 方法中指定的屬性名稱,並附加 "Property"。The naming convention for bindable properties is that the bindable property identifier must match the property name specified in the Create method, with "Property" appended to it. 因此,在上述範例中,可系結的屬性識別碼為 EventNamePropertyTherefore, in the example above, the bindable property identifier is EventNameProperty.

(選擇性)建立BindableProperty實例時,可以指定下列參數:Optionally, when creating a BindableProperty instance, the following parameters can be specified:

  • 繫結模式。The binding mode. 這是用來指定將傳播屬性值變更的方向。This is used to specify the direction in which property value changes will propagate. 在預設系結模式中,變更會從來源傳播至目標In the default binding mode, changes will propagate from the source to the target.
  • 當設定屬性值時,將會叫用的驗證委派。A validation delegate that will be invoked when the property value is set. 如需詳細資訊,請參閱驗證回呼For more information, see Validation callbacks.
  • 當屬性值變更時,將會叫用的屬性變更委派。A property changed delegate that will be invoked when the property value has changed. 如需詳細資訊,請參閱偵測屬性變更For more information, see Detect property changes.
  • 當屬性值變更時,將會叫用的屬性變更委派。A property changing delegate that will be invoked when the property value will change. 這個委派與屬性已變更的委派具有相同的簽章。This delegate has the same signature as the property changed delegate.
  • 當屬性值已變更時,將會叫用的強制型轉值委派。A coerce value delegate that will be invoked when the property value has changed. 如需詳細資訊,請參閱強制型轉值回呼For more information, see Coerce value callbacks.
  • 用來初始化預設屬性值的 FuncA Func that's used to initialize a default property value. 如需詳細資訊,請參閱使用 Func 建立預設值For more information, see Create a default value with a Func.

建立存取子Create accessors

屬性存取子必須使用屬性語法來存取可系結的屬性。Property accessors are required to use property syntax to access a bindable property. Get 存取子應該會傳回包含在對應之可系結屬性中的值。The Get accessor should return the value that's contained in the corresponding bindable property. 呼叫GetValue方法,傳入要取得值的可系結屬性識別碼,然後將結果轉換成所需的型別,即可達成此目的。This can be achieved by calling the GetValue method, passing in the bindable property identifier on which to get the value, and then casting the result to the required type. Set 存取子應設定對應之可系結屬性的值。The Set accessor should set the value of the corresponding bindable property. 呼叫SetValue方法,傳入要設定值的可系結屬性識別碼,以及要設定的值,即可達成此目的。This can be achieved by calling the SetValue method, passing in the bindable property identifier on which to set the value, and the value to set.

下列程式碼範例顯示 EventName 可系結屬性的存取子:The following code example shows accessors for the EventName bindable property:

public string EventName
{
  get { return (string)GetValue (EventNameProperty); }
  set { SetValue (EventNameProperty, value); }
}

使用可系結屬性Consume a bindable property

一旦建立可系結的屬性之後,就可以從 XAML 或程式碼取用它。Once a bindable property has been created, it can be consumed from XAML or code. 在 XAML 中,這是藉由宣告具有前置詞的命名空間來達成,其中命名空間宣告會指示 CLR 命名空間名稱,並選擇性地宣告元件名稱。In XAML, this is achieved by declaring a namespace with a prefix, with the namespace declaration indicating the CLR namespace name, and optionally, an assembly name. 如需詳細資訊,請參閱XAML 命名空間For more information, see XAML Namespaces.

下列程式碼範例示範自訂類型的 XAML 命名空間,其中包含可系結的屬性,其定義在與參考自訂類型的應用程式程式碼相同的元件中:The following code example demonstrates a XAML namespace for a custom type that contains a bindable property, which is defined within the same assembly as the application code that's referencing the custom type:

<ContentPage ... xmlns:local="clr-namespace:EventToCommandBehavior" ...>
  ...
</ContentPage>

設定 EventName 可系結屬性時,會使用命名空間宣告,如下列 XAML 程式碼範例所示:The namespace declaration is used when setting the EventName bindable property, as demonstrated in the following XAML code example:

<ListView ...>
  <ListView.Behaviors>
    <local:EventToCommandBehavior EventName="ItemSelected" ... />
  </ListView.Behaviors>
</ListView>

對等的 C# 程式碼會顯示在以下程式碼範例中:The equivalent C# code is shown in the following code example:

var listView = new ListView ();
listView.Behaviors.Add (new EventToCommandBehavior
{
  EventName = "ItemSelected",
  ...
});

進階案例Advanced scenarios

建立BindableProperty實例時,有一些選擇性參數可設定為啟用 advanced 可系結屬性案例。When creating a BindableProperty instance, there are a number of optional parameters that can be set to enable advanced bindable property scenarios. 本節將探討這些案例。This section explores these scenarios.

偵測屬性變更Detect property changes

static 屬性變更的回呼方法可以透過指定BindableProperty.Create方法的 propertyChanged 參數,向可系結的屬性註冊。A static property-changed callback method can be registered with a bindable property by specifying the propertyChanged parameter for the BindableProperty.Create method. 當可系結屬性的值變更時,將會叫用指定的回呼方法。The specified callback method will be invoked when the value of the bindable property changes.

下列程式碼範例顯示 EventName 可系結屬性如何將 OnEventNameChanged 方法註冊為屬性變更的回呼方法:The following code example shows how the EventName bindable property registers the OnEventNameChanged method as a property-changed callback method:

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 參數的值代表可系結屬性的舊值和新值。In the property-changed callback method, the BindableObject parameter is used to denote which instance of the owning class has reported a change, and the values of the two object parameters represent the old and new values of the bindable property.

驗證回呼Validation callbacks

static 驗證回呼方法可以透過指定BindableProperty.Create方法的 validateValue 參數,向可系結的屬性註冊。A static validation callback method can be registered with a bindable property by specifying the validateValue parameter for the BindableProperty.Create method. 當已設定可系結屬性的值時,將會叫用指定的回呼方法。The specified callback method will be invoked when the value of the bindable property is set.

下列程式碼範例顯示 Angle 可系結屬性如何將 IsValidValue 方法註冊為驗證回呼方法:The following code example shows how the Angle bindable property registers the IsValidValue method as a validation callback method:

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,否則 falseValidation callbacks are provided with a value, and should return true if the value is valid for the property, otherwise false. 如果驗證回呼傳回 false(應由開發人員處理),就會引發例外狀況。An exception will be raised if a validation callback returns false, which should be handled by the developer. 驗證回呼方法的一般用法是在設定可系結屬性時,限制整數或雙精度浮點數的值。A typical use of a validation callback method is constraining the values of integers or doubles when the bindable property is set. 例如,IsValidValue 方法會檢查屬性值是否為0到360範圍內的 doubleFor example, the IsValidValue method checks that the property value is a double within the range 0 to 360.

強制型轉值回呼Coerce value callbacks

static 強制型轉值回呼方法可以透過指定BindableProperty.Create方法的 coerceValue 參數,向可系結的屬性註冊。A static coerce value callback method can be registered with a bindable property by specifying the coerceValue parameter for the BindableProperty.Create method. 當可系結屬性的值變更時,將會叫用指定的回呼方法。The specified callback method will be invoked when the value of the bindable property changes.

重要

BindableObject 類型具有 CoerceValue 方法,可透過叫用其強制轉型值回呼,加以呼叫來強制重新評估其 BindableProperty 引數的值。The BindableObject type has a CoerceValue method that can be called to force a reevaluation of the value of its BindableProperty argument, by invoking its coerce value callback.

當屬性的值變更時,強制重新評估可系結屬性的強制值回呼。Coerce value callbacks are used to force a reevaluation of a bindable property when the value of the property changes. 例如,強制型轉值回呼可以用來確保一個可系結屬性的值不大於另一個可系結屬性的值。For example, a coerce value callback can be used to ensure that the value of one bindable property is not greater than the value of another bindable property.

下列程式碼範例顯示 Angle 可系結屬性如何將 CoerceAngle 方法註冊為強制值回呼方法:The following code example shows how the Angle bindable property registers the CoerceAngle method as a coerce value callback method:

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 屬性值。The CoerceAngle method checks the value of the MaximumAngle property, and if the Angle property value is greater than it, it coerces the value to the MaximumAngle property value. 此外,當 MaximumAngle 屬性變更時,會藉由呼叫 CoerceValue 方法,在 Angle 屬性上叫用強制轉型值回呼。In addition, when the MaximumAngle property changes the coerce value callback is invoked on the Angle property by calling the CoerceValue method.

使用 Func 建立預設值Create a default value with a Func

Func 可以用來初始化可系結屬性的預設值,如下列程式碼範例所示:A Func can be used to initialize the default value of a bindable property, as demonstrated in the following code example:

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方法,以傳回代表在原生平臺上用於Label之字型的已命名大小的 doubleThe defaultValueCreator parameter is set to a Func that invokes the Device.GetNamedSize method to return a double that represents the named size for the font that is used on a Label on the native platform.