最近のブログで、DelphiのRTLコアの式エンジンとコンポーネントのバインディングについて説明しました。シリーズの第3回となる今回のブログでは、さらに一歩進んでバインディングアーキテクチャ全体の重要なコンポーネントである「BindingsList 」について見ていきましょう。バインディングリストとは、さまざまな種類のバインディング式のコレクションで、デザイナで管理されています。
前回のブログでソースコードで定義した式やコンポーネントのバインディングは、BindingsListコンポーネントのデザイナとウィザードを利用することで、コードを書かずに完全に定義することができます。
では、実際にBindingsListコンポーネントの使い方を見ていきましょう。
ここでは、簡単の例ですが、下図のようにTEditを2つ、TSpinEdit、TProgressBar、そしてTBindingListコンポーネントをそれぞれフォーム上に配置します。
BindingsListコンポーネントには、バインディングのコレクションを定義できるデザイナがあります。各バインディングは、数多くの利用可能なオプションから選択することができます。
以下の図のようにフォームデザイン画面で、フォーム上のTBindingsListコンポーネントを選択し、マウスを右クリックするとポップアップメニューから表示されます。そのメニューのうち”LiveBindingコンポーネントの新規作成”を選択すると、リストの中からバインディングクラスを選択することができます。
ただし、バインディングのコレクションの種類は多いため、このブログでは、主にデータソースとデータフィールドのバインディングに焦点を当てます。ここではTBindExpressionとTBindExprItemsの2つの基本的なオプションを使用する例を紹介いたします。
TBindExpressionを利用したバインディング
まず1つ目の例としてTBindExpressionのバインディングクラスを選択し、2つのコンポーネントをバインディングしてみましょう。
上図のコレクションクラスのリストからTBindExpressionを選択すると、バインドコンポーネントのリストに”BindExpression1”という名前のコンポーネントが登録されます。(ここでの例は、BindExpression1ですが、任意の名前に変更可)
このBindExpression1を選択すると、 下図のようにオブジェクトインスペクタにBindExpression1のプロパティが表示されます。
オブジェクトインスペクタで、TBindExpressionクラスのSourceComponentやControlComponent(ターゲットコントロールを指す用語)などの式のプロパティを設定し、コンポーネントに関連する式を設定することができます。
ここでは、SpinEdit1のValueプロパティをProgressBar1のPosiitonプロパティに反映させるため、BindExpression1のプロパティをSourceComponentをSpinEdit1、ControlComponentをProgressBar1に変更します。
Directionプロパティは、バインディング式を実施する方向を示しています。
- dirSourceToControl(コントロールに割り当て)
- dirControlToSource(ソースへの代入)
- dirBidirectional(双方向の代入)
の中から選択できますが、ここではデフォルトのdirSourceToControlのままで構いません。
最後に式を定義します。ProgressBar1のコントロール式:にPositionを入力し、SpinEdit1のソース式:にValueを入力します。BindExpression1の各プロパティを変更すると、下図のようにバインドコンポーネントのリストが更新されます。
上図では、ソースコントロールとターゲットコントロールに式を繋げています。ここではProgressBar1とSpinEdit1に対してそれぞれ式が定義されており、この式はSpinEdit1.Value(ソース)からProgressBar1.Position(コントロール)の単方向に反映することを意味しています。
式の定義は、単一のプロパティ名のような単純な形式から、値と式を組み合わせた複雑な形式まであり、オブジェクトインスペクタの式のプロパティで設定、あるいは上図に表示されている特別なデザイナで設定することができます。なおデザイナには、さまざまな式を評価、検査するオプションも用意されています。
TBindExprItemsを利用したバインディング
続いて2つ目の例としてTBindExprItemsのバインディングクラスを選択し、2つのエディットボックス(TEditコンポーネント)をバインディングしてみましょう。TBindExprItemsは、より複雑なバインディングで、ソースとコントロールを指定しますが(1つ目の例と同様)、コントロールの複数のプロパティを含めることが可能で、クリアおよび書式のコレクションを定義できます。
ここでの例では、2つのエディットボックスに新しい書式を作成して双方向のバインディングを行い、いずれかのエディットボックスにテキストを入力すると、もう一方のエディットボックスのテキストに反映されるように設定してみましょう。
(1) ”LiveBindingコンポーネントの新規作成”から、TBindExprItemsを追加します。(ここでの例はBindExprItems1ですが、任意の名前に変更可)
(2)バインドコンポーネントのリストからBindExprItems1を選択し、オブジェクトインスペクタでBindExprItems1プロパティのSourceComponentをEdit1、ControlComponentをEdit2に変更します。(下図を参照)
(3)BindExprItems1に式を追加するため、バインドコンポーネントの一覧からBindExprItems1を選択して、マウスをダブルクリックしてください。下図のようにBindExprItems1の編集画面が表示されます。
上図のBindExprItems1の編集画面の右側にコレクションのリストがあります。書式が選択されている状態で、マウスを右クリックすると、下図のように追加のメニューが表示されます。
[追加]ボタンを選択すると、下図のように書式[0]が追加されます。
(4) 書式[0]を選択し、Edit1のコントロール式:にTextを入力、Edit2のソース式:にTextを入力します。そしてオブジェクトインスペクタでBindExprItems1.FormatExpression[0]のDirectionプロパティをdirBidirectional(双方向)に変更します。(下図を参照)
上記の設定によって2つのエディットボックスは、Text to Text(双方向)にマッピングされ、いずれかのエディットボックスにテキストを入力すると、もう一方のエディットボックスのテキストに反映されます。
前回のブログでは、2つのコンポーネントのバインディングを行う際、Delphiコードで記述しましたが、BindingsListコンポーネントのデザイナを使用すると、コードを書かずにバインディングを行うことができます。なお、これらのバインディングに関する情報は、オブジェクトインスペクタで編集した他のオブジェクトと同様にフォームファイル(VCLの場合は.dfmファイル、FMXの場合は.frmファイル)に保持されます。以下は、ここで紹介したサンプルプログラムで設定したBindingsListコンポーネントの例です。
[crayon-67687236d5faa006442421/]デザイナで編集したフォームファイルはテキスト形式で保存されているため、このデータの内容自体はブラックボックスではありません(データ構造を正しく理解していれば、編集することもできます)。例えば、デザイナ画面でこのブログの手順で扱った該当コンポーネントをフォームへ配置し、上記のコンポーネントの情報をコピーして既存のフォームファイルに追加あるいは置き換えれば、同様のバインディング動作になるはずです。
以上でバインディングの設定は完了ですが、最後にコンポーネントの値が変更されたとき、ソースコントロールからバインディングされたターゲットコントロールへ通知するためのコードの実装が必要です。以下のコード例のように OnChangeイベントハンドラ内で現在のコントロール(Sender)のバインディングをTBindings.Notifyで実行すると、簡単に実装できます。
[crayon-67687236d5fb2457345388/]このプロジェクトをビルドし、実行したアプリケーションの画面例は、以下の通りです。
今回は、ここまでとなります。このブログでバインディングアーキテクチャの一面について簡単に触れましたが、式とバインディングに関するこのシリーズの次のステップは、Visual Live Binding デザイナです。次回は、このブログで紹介いたしました内容をベースにしてVisual Live Binding デザイナに関してもう少し詳しく取り上げます。