第 11 章の概要: バインド可能なインフラストラクチャ

サンプルのダウンロードサンプルのダウンロード

注意

この本は 2016 年春に発行されて以降、改訂されていません。 多くの情報はまだ価値がありますが、一部の資料は古くなっており、トピックの中にはまったく正しくないものまたは不完全なものもあります。

すべての C# プログラマは、C# の "プロパティ" について理解しています。 プロパティには、set アクセサーと get アクセサーのどちらか一方または両方が含まれます。 それらは、共通言語ランタイムの "CLR プロパティ" と呼ばれることがよくあります。

Xamarin.Forms では、BindableProperty クラスによってカプセル化され、BindableObject クラスによってサポートされる、"バインド可能プロパティ" と呼ばれる拡張プロパティ定義が定義されています。 これらのクラスは関連してはいますが、非常に異なります。BindableProperty は、プロパティ自体を定義するために使用されます。BindableObject は、バインド可能プロパティを定義するクラスの基底クラスであるという点で object に似ています。

Xamarin.Forms のクラス階層

ClassHierarchy サンプルでは、リフレクションを使用して Xamarin.Forms のクラス階層が表示され、この階層において BindableObject によって果たされる重要な役割が示されています。 BindableObject は、Object から派生し、それを親クラスとする Element から、VisualElement が派生します。 さらにこれを親として PageView が派生し、それは Layout に対する親クラスです。

クラス階層共有のトリプル スクリーンショット

BindableObject と BindableProperty の詳細

BindableObject から派生したクラスでは、多くの CLR プロパティがバインド可能プロパティ "によってサポートされている" と言われます。 たとえば、Label クラスの Text プロパティは CLR プロパティですが、Label クラスでは、 型の BindablePropertyTextProperty という名前のパブリックな静的読み取り専用フィールドも定義されています。

アプリケーションは、 の プロパティLabelText通常どおりに設定または取得できます。または、 で定義されたメソッドを引数でLabel.TextProperty呼び出すことで、アプリケーションで BindableObjectSetValue設定Textできます。 同様に、アプリケーションは、 メソッドを呼び出してプロパティの Text 値を GetValue 取得できます。もう一度引数を指定 Label.TextProperty します。 これについては、PropertySettings サンプルを参照してください。

実際には、Text CLR プロパティは、BindableObjectLabel.TextProperty 静的プロパティの組み合わせによって定義された SetValue メソッドと GetValue メソッドを使用して、完全に実装されます。

BindableObjectBindableProperty では、以下に対するサポートが提供されます。

  • プロパティの既定値の指定
  • 現在の値の格納
  • プロパティ値を検証するためのメカニズムの提供
  • 1 つのクラスの関連するプロパティ間の整合性の維持
  • プロパティの変更への応答
  • プロパティが変更されようとしているとき、または変更されたときの通知のトリガー
  • データ バインディングのサポート
  • スタイルのサポート
  • 動的リソースのサポート

バインド可能プロパティによってサポートされるプロパティが変更されるたびに、BindableObject によって、変更されたプロパティを示す PropertyChanged イベントが生成されます。 プロパティが同じ値に設定されたときは、このイベントは生成されません。

一部のプロパティはバインド可能なプロパティによってサポートされず、 などのSpan一部Xamarin.Formsのクラスは からBindableObject派生しません。 BindableObjectSetValue メソッドと GetValue メソッドが定義されているため、BindableObject から派生したクラスのみがバインド可能プロパティをサポートできます。

Spanは からBindableObject派生しないため、そのプロパティ (などText) はバインド可能なプロパティによってサポートされません。 このため、SpanText プロパティで DynamicResource を設定すると、前の章の DynamicVsStatic サンプルで例外が発生します。 DynamicVsStaticCode サンプルでは、 でElement定義された メソッドを使用して、コード内で動的リソースを設定するSetDynamicResource方法を示します。 最初の引数は BindableProperty 型のオブジェクトです。

同様に、 で定義されるSetBindingメソッドには、 型の最初の引数がありますBindablePropertyBindableObject

バインド可能プロパティの定義

静的 BindableProperty.Create メソッドを使用して、独自のバインド可能なプロパティを定義して、 型 BindablePropertyの静的読み取り専用フィールドを作成できます。

これは、Book.Toolkit ライブラリの AltLabel クラスでXamarin.Forms示されています。 そのクラスは Label から派生し、フォント サイズをポイント単位で指定できます。 PointSizedText サンプルを参照してください。

BindableProperty.Create メソッドの 4 つの引数は必須です。

  • propertyName: プロパティのテキスト名 (CLR プロパティ名と同じ)
  • returnType: CLR プロパティの型
  • declaringType: プロパティを宣言するクラスの型
  • defaultValue: プロパティの既定値

defaultValueobject 型であるため、コンパイラは既定値の型を決定できる必要があります。 たとえば、returnTypedouble である場合、defaultValue は単に 0 ではなく 0.0 のように設定する必要があります。そうしないと、型の不一致によって実行時に例外が発生します。

また、バインド可能プロパティに次のものが含まれるのもよくあることです。

  • propertyChanged: プロパティの値が変更されたときに呼び出される静的メソッド。 最初の引数は、プロパティが変更されたクラスのインスタンスです。

BindableProperty.Create に対する他の引数は、一般的ではありません。

  • defaultBindingMode: データ バインディングとの関係で使用されます (「第 16 章「データ バインディング」を参照)。
  • validateValue: 有効な値を確認するためのコールバック
  • propertyChanging: プロパティが変更されようとしていることを示すコールバック
  • coerceValue: set 値を別の値に強制的に変換するためのコールバック
  • defaultValueCreate: クラスのインスタンス間で共有できない既定値を作成するためのコールバック (たとえば、コレクション)

読み取り専用のバインド可能プロパティ

バインド可能プロパティは読み取り専用にできます。 読み取り専用のバインド可能なプロパティを作成するには、静的メソッド BindableProperty.CreateReadOnly を呼び出して、 型 BindablePropertyKeyのプライベート静的読み取り専用フィールドを定義する必要があります。

次に、 オブジェクトを使用してオーバーロードを呼び出SetValueすように CLR プロパティ set の accesor privateBindablePropertyKey定義します。 これにより、プロパティがクラスの外部で設定されるのを防ぐことができます。

これは、BaskervillesCount サンプルで使用されるクラスで示されていますCountedLabel