Note
この本は 2016 年春に発行されて以降、改訂されていません。 多くの情報はまだ価値がありますが、一部の資料は古くなっており、トピックの中にはまったく正しくないものまたは不完全なものもあります。
プログラマーは、あるオブジェクトのプロパティが変更されたことを検出するイベント ハンドラーを作成し、それを使って別のオブジェクトのプロパティの値を変更することがよくあります。 このプロセスは、"データ バインディング" の手法を使用して自動化できます。 データ バインディングは、通常、XAML で定義され、ユーザー インターフェイスの定義の一部になります。
非常に多くの場合、このようなデータ バインディングによって、ユーザー インターフェイス オブジェクトが基になるデータに接続されます。 これは、次でさらに詳しく調べる手法です: 第18章: MVVM。 ただし、データ バインディングでは、2 つ以上のユーザー インターフェイス要素を接続することもできます。 この章に記載されているデータ バインディングの初期の例のほとんどは、この手法を示しています。
バインディングの基礎
データ バインディングでは、いくつかのプロパティ、メソッド、およびクラスが使用されます。
BindingクラスはBindingBaseから派生し、データ バインディングの多くの特性をカプセル化しますBindingContextプロパティは、BindableObjectクラスによって定義されますSetBindingメソッドも、BindableObjectクラスによって定義されますBindableObjectExtensionsクラスは、3 つの追加のSetBindingメソッドを定義します
次の 2 つのクラスでは、バインディング用の XAML マークアップ拡張機能がサポートされています。
BindingExtensionではBindingマークアップ拡張機能がサポートされていますReferenceExtensionではx:Referenceマークアップ拡張機能がサポートされています
データ バインディングでは、次の 2 つのインターフェイスが使用されます。
System.ComponentModel名前空間のINotifyPropertyChangedを使って、プロパティが変更されたときの通知が実装されますIValueConverterは、データ バインディングにおいて値をある型から別の型に変換する、小規模のクラスを定義するために使用されます
データ バインディングによって、同じオブジェクトの 2 つのプロパティ、または (より一般的には) 2 つの異なるオブジェクトの 2 つのプロパティが接続されます。 これらの 2 つのプロパティは、"ソース" と "ターゲット" と呼ばれます。 一般に、ソース プロパティの変更によってターゲット プロパティの変更が発生しますが、この方向は逆になることがあります。 いずれにしても:
- "ターゲット" プロパティは
BindablePropertyによってサポートされている必要があります - "ソース" プロパティは、通常、
INotifyPropertyChangedを実装するクラスのメンバーです
INotifyPropertyChanged を実装するクラスでは、プロパティの値が変更されると PropertyChanged イベントが発生します。 BindableObject では INotifyPropertyChanged が実装されているため、BindableProperty によってサポートされているプロパティの値が変更されると PropertyChanged イベントが自動的に発生します。ただし、INotifyPropertyChanged を実装する独自のクラスを、BindableObject から派生することなく作成することもできます。
コードと XAML
OpacityBindingCode サンプルでは、コードでデータ バインディングを設定する方法が示されています。
- ソースは、
SliderのValueプロパティです - ターゲットは、
LabelのOpacityプロパティです
2 つのオブジェクトは、Label オブジェクトの BindingContext を Slider オブジェクトに設定することによって接続されます。 2 つのプロパティは、バインド可能なプロパティ OpacityProperty と、文字列として表される Slider の Value プロパティを参照する、Label の SetBinding 拡張メソッドを呼び出すことによって接続されます。
Slider を操作すると、Label の表示がフェード イン、フェード アウトされます。
OpacityBindingXaml は、XAML でデータ バインディングが設定された同じプログラムです。 Label の BindingContext は、Slider を参照する x:Reference マークアップ拡張に設定され、Label の Opacity プロパティは、Slider の Value プロパティを参照するその Path プロパティを使用して、Binding マークアップ拡張に設定されます。
ソースと BindingContext
BindingSourceCode サンプルでは、コードにおける別のアプローチが示されています。 Binding オブジェクトは、Source プロパティを Slider オブジェクトに設定し、Path プロパティを "Value" に設定することで作成されます。 次に、Label オブジェクトで BindableObject の SetBinding メソッドが呼び出されます。
Binding コンストラクターを使用して Binding オブジェクトを定義することもできます。
BindingSourceXaml サンプルには、XAML での同等の手法が示されています。 Label の Opacity プロパティは Binding マークアップ拡張に設定され、Path は Value プロパティに、Source は埋め込みの x:Reference マークアップ拡張に設定されます。
要約すると、バインディング ソース オブジェクトを参照するには、次の 2 つの方法があります。
- ターゲットの
BindingContextプロパティを使用する Bindingオブジェクト自体のSourceプロパティを使用する
両方を指定した場合は、2 番目が優先されます。 BindingContext の利点は、それがビジュアル ツリーを通じて伝達されることです。 これは、複数のターゲット プロパティが同じソース オブジェクトにバインドされている場合に、"非常に" 便利です。
WebViewDemo プログラムでは、WebView 要素を使ってこの手法が示されています。 前後に移動するための 2 つの Button 要素は、WebView を参照するその親から BindingContext を継承します。 次に、2 つのボタンの IsEnabled プロパティでは、WebView の読み取り専用プロパティ CanGoBack および CanGoForward の設定に基づいて、ボタンの IsEnabled プロパティをターゲットとする Binding マークアップ拡張が設定されています。
バインディング モード
Binding の Mode プロパティを、次の BindingMode 列挙型のメンバーに設定します。
OneWay: ソース プロパティに対する変更がターゲットに影響を与えるようにしますOneWayToSource: ターゲット プロパティに対する変更がソースに影響を与えるようにしますTwoWay: ソースとターゲットに対する変更が相互に影響を与えるようにしますDefault: ターゲットのBindablePropertyが作成されたときに指定されたDefaultBindingModeを使用します。 何も指定されていなかった場合、既定値は、通常のバインド可能なプロパティの場合はOneWay、読み取り専用のバインド可能なプロパティの場合はOneWayToSourceになります。
Note
BindingMode 列挙型には、ソース プロパティが変更されたときではなく、バインディング コンテキストが変更されたときにのみバインディングを適用するための OnTime も含まれるようになりました。
MVVM シナリオにおいてデータ バインディングのターゲットとなる可能性のあるプロパティには、通常、TwoWay の DefaultBindingMode が設定されています。 次のとおりです。
SliderとStepperのValueプロパティSwitchのIsToggledプロパティEntry、Editor、SearchBarのTextプロパティDatePickerのDateプロパティTimePickerのTimeプロパティ
BindingModes サンプルでは、ターゲットが Label の FontSize プロパティであり、ソースが Slider の Value プロパティであるデータ バインディングを使用した、4 つのバインディング モードが示されています。 これにより、各 Slider で対応する Label のフォント サイズを制御できるようになります。 ただし、Slider 要素は初期化されません。FontSize プロパティの DefaultBindingMode が OneWay であるためです。
ReverseBinding サンプルでは、各 Label の FontSize プロパティを参照する、Slider の Value プロパティのバインディングが設定されています。 これは後退しているように見えますが、Slider の Value プロパティの DefaultBindingMode が TwoWay であるため、Slider 要素をより適切に初期化することができます。
これは、MVVM でバインディングが定義される方法に似ています。この種類のバインディングは頻繁に使用します。
文字列の書式設定
ターゲット プロパティの型が string の場合、BindingBase によって定義されている StringFormat プロパティを使用して、ソースを string に変換できます。 オブジェクトを表示する静的な String.Format 書式設定を使用して、StringFormat プロパティを、使用する .NET 書式設定文字列に設定します。 マークアップ拡張内でこの書式設定文字列を使用する場合は、中かっこが埋め込みマークアップ拡張と間違えられないように、これを単一引用符で囲んでください。
ShowViewValues サンプルでは、XAML で StringFormat を使用する方法が示されています。
WhatSizeBindings サンプルでは、ContentPage の Width および Height プロパティへのバインディングを使用して、ページのサイズを表示する方法が示されています。
"Path" と呼ばれる理由
Binding の Path プロパティがこのように呼ばれるのは、ピリオドで区切られた一連のプロパティとインデクサーを指定できるためです。 BindingPathDemos サンプルでは、いくつかの例が示されています。
バインディングの値コンバーター
バインディングのソース プロパティとターゲット プロパティが異なる型である場合は、バインディング コンバーターを使用して型の間で変換を行うことができます。 これは、IValueConverter インターフェイスを実装したクラスであり、2 つのメソッドが含まれています。ソースをターゲットに変換するための Convert と、ターゲットをソースに変換するための ConvertBack です。
Xamarin.FormsBook.Toolkit ライブラリの IntToBoolConverter クラスは、int を bool に変換する 1 つの例です。 これは ButtonEnabler サンプルで示されています。そこでは、少なくとも 1 つの文字が Entry に入力された場合にのみ、Button が有効になります。
BoolToStringConverter クラスでは、bool が string に変換され、false と true の値に対して返されるテキストを指定するために、2 つのプロパティが定義されています。
BoolToColorConverter も似ています。 SwitchText サンプルでは、これら 2 つのコンバーターを使用して、Switch 設定に基づいてさまざまなテキストをさまざまな色で表示する方法が示されています。
ジェネリックの BoolToObjectConverter では、BoolToStringConverter と BoolToColorConverter を置き換えることができます。これは、汎用的な、bool からオブジェクトへの任意の型のコンバーターとして機能します。
バインディングとカスタム ビュー
データ バインディングを使用してカスタム コントロールを簡略化できます。 NewCheckBox.cs コード ファイルでは、Text、TextColor、FontSize、FontAttributes、および IsChecked プロパティが定義されていますが、コントロールのビジュアル用のロジックはまったく含まれていません。
代わりに、NewCheckBox.cs.xaml ファイルには、分離コード ファイル内で定義されているプロパティに基づき、Label 要素のデータ バインディングを使用して、コントロールのビジュアルに対するすべてのマークアップが含まれています。
NewCheckBoxDemo サンプルでは、NewCheckBox カスタム コントロールが示されています。
