データバインディングの概要
データバインディングとは、ユーザーインターフェイスのプロパティと他のコントロールやクラスのプロパティを関連づける処理のことです。データバインディングは主に、データベースやWebサービスなどから取得したリソースを、クライアント上のコントロールに表示する場合などに利用します。
データバインディングを使わない場合は、「リソースを順に取得しながら、対応するコントロールのプロパティに代入する」といったコードが必要になります。例えば、次のようなコードになります。
var resource = getResource(); //データベースやWebサービスなどからリソースを取得 nameTextBox.Text = resource.Name; //テキストボックスに値を代入 addressTextBlock.Text = resource.Address; //テキストブロックに値を代入
一方、データバインディングを使えば、「このコントロールには○○というフィールドを表示させる」という設定をしておくだけで、実際の値の割り当て(=バインディング)は自動的に行われます。詳細は後で扱いますが、データバインディングがどれぐらい簡潔な記述でできるかを少し見てみましょう。XAMLコード側では次のようにコントロールと、割り当てるプロパティを関連づけます。
<TextBox Text="{Binding Path=Name}" x:Name="nameTextBox"/> <TextBlock Text="{Binding Path=Address}" x:Name="addressTextBlock"/>
合わせて分離コードで、バインドするオブジェクトを指定します。
var resource = getResource(); //データベースやWebサービスなどからリソースを取得 this.DataContext = resource; //バインド元オブジェクトを設定
バインドするコントロールが少ない場合は、データバインディングを使わないコードでも対応できますが、多数のコントロールを使うケースや、データ数に応じてコントロールの数を増減させる場合などは、データバインディングを使った方がずっと楽になります。
特に、業務アプリケーションの多くは、一般に帳票画面と呼ばれるリソースを表示・編集する画面の集合でできており、この実装においてデータバインディングは欠かせない技術と言えます。
.NET Framework 3.5のWPFは強力なデータバインディングをサポートしていますが、そのサブセット的位置づけにあるSilverlight 2もやはり多彩なデータバインディングに対応しています。本稿ではSilverlight 2のデータバインディングの概要と業務アプリケーションへの実装について扱います。
バインド元オブジェクト
Silverlight 2におけるバインド元のオブジェクトですが、SOAP、RSS、Webサービスを経由したXMLサービスやデータベースなどさまざまなものが使えます。各種データソースをNET Framework3.5の新機能であるLINQを利用して、加工してからバインドすることも可能です。また、コード内に実データを埋め込んでおき、それをバインド元にすることもできます。
Silverlight 2のデータバインドモード
Silverlight 2のデータバインディングには次の3つのモードがあります。
モード | 概要 |
OneTime | バインドされた時点のオブジェクトの値がコントロールに反映される。以後、オブジェクトの値が更新されても、コントロールは更新されない。 |
OneWay | バインドされた時点のオブジェクトの値がコントロールに反映され、以後、オブジェクトの値が更新されるたびに、コントロールが更新される。 |
TwoWay | OneWayに加え、コントロールの値が更新された場合にも、オブジェクトの値に反映される。 |
OneTimeバインディングは固定値をバインドするモードです。バインド先でデータソースが指定された時点で一度だけバインドが実行されます。バインド後に元データが変化しても、コントロールには反映されません。データソースの更新がほとんど生じない場合はOneTimeバインドを使用するのが良いでしょう。
OneWayバインディングはその名の通り片方向からのバインドモードで、バインド元データソースの変化にリアルタイムに対応し、バインド先の表示データが追随する形で動作します。
TwoWayバインディングは双方向のバインドモードです。バインド元またバインド先双方からのデータ更新機能を実装したい場合に使用します。ちなみに、WPFのデータバインドではデフォルトのモードがTwoWayになっていましたが、SilverlightではデフォルトがOneWayになります。この点、WPFでの実装経験のある開発者は注意が必要です。
なお、バインドモードとしてOneWayおよびTwoWayを使う場合には、バインドするオブジェクトはINotifyPropertyChangedインターフェイスを実装する必要があります。これはオブジェクトの値が更新されたことを検出するためのインターフェイスです。
Silverlight 2のバインド先とDataContext
Silverlight 2では、実質的にほとんどのコントロールのプロパティをデータバインディングの対象とすることが可能です。TextBlockコントロールのText
プロパティのような、画面に表示されるプロパティにバインドするのが一般的ですが、スタイル指定のプロパティや、コントロールの位置にオブジェクトの値をバインドすることも可能です。
バインディングを行う場合はXAMLでユーザーインターフェイスを定義する際に、{Binding …}
のような特殊な構文を使用します。例えば、TextBlockコントロールのText
プロパティにバインディングで値を設定する場合は下のように記述します。
<TextBlock Text="{Binding Path=FirstName Mode=OneWay}" />
この場合、Text
プロパティに、バインド元オブジェクトのFirstName
プロパティの値がOneWayモードでバインディングされます。
さて、今の構文においては、プロパティの種類のみが指定され、バインド元オブジェクトが明示されていないことに気づかれたかと思います。Silverlightのデータバインドは、コントロールごとに特定のバインド元オブジェクトを指定することもできますが、特に指定しない場合は親コントロールのDataContext
プロパティで指定されたオブジェクトが継承されます。下にDataContext
プロパティの設定例を示します。
object1.FirstName = "Hello,World!"; this.DataContext = object1;
この記述の場合、バインド元オブジェトとしてobject1が指定されています。従って、先ほどのTextBlockにバインドされるのはobject1のFirstName
プロパティ、つまり、"Hello,World!"という文字列になります。もちろんこの例ではobject1はFirstName
プロパティを持つクラスのインスタンスでなければなりません。
前述の通り、ユーザーコントロールのDataContext
プロパティはそのユーザーコントロール以下に配置されたコントロールに継承されます。例えばGridやStackPanelといったレイアウト系のコントロールにDataContextを設定すると、それら以下のコントロールにも同様に設定したDataContextが適用されます。
一方、データソースを指定してバインドする場合は次のように記述します。
<TextBlock x:Name="textBlock" Text="{Binding Source={StaticResource bindSource} }" /> <!-- //Text属性に固定ソースを指定してバインディング -->
public Page() { InitializeComponent(); string firstName= "Hello,World!"; Binding bindSource = new Binding(); bindSource.Source = firstName; //バインド先に対応した型のソースを指定 textBlock.SetBinding(textBlock.TextProperty, bindSource); }
ここでは、バインド情報bindSourceにテキストデータを設定し、XAML側で固定ソースとしてバインドしています。