第 16 章の概要: データ バインディング
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
カスタム コントロールが示されています。