データ バインディングの概要 (Windows フォーム .NET)

Windows フォームでは、従来のデータ ソースだけでなく、データを含むほぼすべての構造にバインドできます。 実行時に計算する値、ファイルから読み取る値、または他のコントロールの値から派生する値の配列にバインドできます。

さらに、任意のコントロールのプロパティをデータ ソースにバインドできます。 従来のデータ バインディングでは、通常は Text コントロールの TextBox プロパティなどの表示プロパティをデータ ソースにバインドします。 .NET を使うと、バインディングによってその他のプロパティを設定することもできます。 バインディングを使用して、次のタスクを実行できます。

  • イメージ コントロールのグラフィックの設定。

  • 1 つ以上のコントロールの背景色の設定。

  • コントロール サイズの設定。

基本的には、データ バインディングは、フォーム上の任意のコントロールの実行時にアクセス可能なプロパティを自動的に設定する方法です。

ADO.NET を使うと、アプリケーションのバインディングのニーズや使うデータに合わせてさまざまなデータ構造を作成できます。 Windows フォームでデータを提供または使用するための独自のクラスを作成することもできます。 このようなオブジェクトでさまざまなレベルの機能と複雑さを提供できます。 たとえば、基本的なデータ バインディングをはじめ、デザイン時のサポート、エラー チェック、変更通知、さらにはデータ自体に加えられた変更の構造的なロールバックのサポートなどです。

データ バインディング インターフェイスのコンシューマー

以下のセクションでは、インターフェイス オブジェクトの 2 つのグループについて説明します。 インターフェイスの 1 つ目のグループは、データ ソース作成者がデータ ソースに実装します。 Windows フォーム コントロールやコンポーネントなどのデータ ソース コンシューマーは、これらのインターフェイスを実装します。 インターフェイスの 2 つ目のグループは、コンポーネント作成者が使うように設計されています。 コンポーネント作成者は、Windows フォーム データ バインディング エンジンが使うデータ バインディングをサポートするコンポーネントを作成するときに、これらのインターフェイスを使います。 フォームに関連付けられたクラス内でこれらのインターフェイスを実装することで、データ バインディングを実現できます。 各ケースには、データとの対話を可能にするインターフェイスを実装したクラスが用意されています。 Visual Studio の RAD (Rapid Application Development) データ デザイン エクスペリエンス ツールでは、この機能を既に活用しています。

データ ソース作成者の実装用インターフェイス

Windows フォーム コントロールは以下のインターフェイスを実装しています。

  • IList インターフェイス

    IList インターフェイスを実装するクラスには、ArrayArrayListCollectionBase があります。 これらは型 Object の項目のインデックス付きリストです。インデックスの最初の項目によって型が決まるので、このリストには同種の型を含める必要があります。 IList は、実行時にのみバインドに使用できます。

    注意

    Windows フォームにバインドするためにビジネス オブジェクトのリストを作成する場合は、BindingList<T> を使用することを検討してください。 BindingList は、双方向の Windows フォーム データ バインディングに必要な主要インターフェイスを実装する拡張可能なクラスです。

  • IBindingList インターフェイス

    IBindingList インターフェイスを実装するクラスは、非常に高レベルのデータ バインディング機能を提供します。 この実装は基本的な並べ替え機能と変更通知機能を備えています。 どちらも、リスト項目が変更されたときや、リスト自体が変更されたときに便利です。 複数のコントロールを同じデータにバインドする予定がある場合、変更通知が重要です。 あるコントロールに加えられたデータの変更を、他のバインドされたコントロールに伝達するのに役立ちます。

    注意

    IBindingList インターフェイスの変更通知は、SupportsChangeNotification プロパティによって有効化されます。このプロパティが true の場合に ListChanged イベントが発生し、リストまたはリスト内の項目が変更されたことが示されます。

    変更の種類は、ListChangedEventArgs パラメーターの ListChangedType プロパティで示されます。 したがって、データ モデルが更新されるたびに、依存するビュー (同じデータ ソースにバインドされた他のコントロールなど) も更新されます。 ただし、リストで ListChanged イベントを発生させることができるように、リストに含まれるオブジェクトは、変更時にリストに通知する必要があります。

    注意

    BindingList<T> は、IBindingList インターフェイスの汎用実装です。

  • IBindingListView インターフェイス

    IBindingListView インターフェイスを実装するクラスは、IBindingList の実装のすべての機能に加え、フィルター処理機能と高度な並べ替え機能も備えています。 この実装では、文字列ベースのフィルター処理と、プロパティ記述子と方向のペアによる複数列の並べ替え機能を提供します。

  • IEditableObject インターフェイス

    IEditableObject インターフェイスを実装するクラスでは、オブジェクトへの変更をいつ永続化するかをそのオブジェクトが制御できます。 この実装は BeginEditEndEditCancelEdit の各メソッドをサポートしているので、オブジェクトに加えた変更のロールバックが可能になります。 BeginEditEndEditCancelEdit の各メソッドの機能と、これらが相互に連携して、データに加えられた変更のロールバックを実現するしくみについて、以下に簡単に説明します。

    • BeginEdit メソッドは、オブジェクトの編集の開始を通知します。 このインターフェイスを実装するオブジェクトは、CancelEdit メソッドが呼び出された場合に更新を破棄できる方法で、BeginEdit メソッドの呼び出し後に行われたすべての更新を保存する必要があります。 Windows フォームのデータ バインディングでは、1 つの編集トランザクションのスコープ内で、(BeginEditBeginEditEndEdit のように) BeginEdit を複数回呼び出すことができます。 IEditableObject の実装では、BeginEdit が既に呼び出されているかどうかを追跡し、以降の BeginEdit の呼び出しを無視する必要があります。 このメソッドは複数回呼び出すことができるため、後続の呼び出しを非破壊的にすることが重要です。 後続の BeginEdit 呼び出しで、加えられた更新を破棄することや、最初の BeginEdit 呼び出しで保存されたデータを変更することはできません。

    • 基になるオブジェクトが現在編集モードの場合、EndEdit メソッドは、BeginEdit が呼び出された後に加えられたすべての変更をオブジェクトにプッシュします。

    • CancelEdit メソッドは、オブジェクトに加えられたすべての変更を破棄します。

    BeginEditEndEditCancelEdit の各メソッドの機能の詳細については、「データをデータベースに保存する」を参照してください。

    データ機能のこのトランザクションの概念は、DataGridView コントロールで使用されています。

  • ICancelAddNew インターフェイス

    ICancelAddNew インターフェイスを実装するクラスでは、通常は IBindingList インターフェイスを実装し、AddNew メソッドによるデータ ソースへの追加をロールバックできるようにします。 データ ソースが IBindingList インターフェイスを実装している場合は、ICancelAddNew インターフェイスも実装する必要があります。

  • IDataErrorInfo インターフェイス

    IDataErrorInfo インターフェイスを実装するクラスでは、オブジェクトはバインドされたコントロールにカスタム エラー情報を提供できます。

    • Error プロパティは、一般的なエラー メッセージ テキスト (例: "エラーが発生しました") を返します。

    • Item[] プロパティは、列の具体的なエラー メッセージを含む文字列 (例: "State 列の値が無効です") を返します。

  • IEnumerable インターフェイス

    IEnumerable インターフェイスを実装するクラスは、一般に ASP.NET によって使用されます。 Windows フォームによるこのインターフェイスのサポートを利用できるようにするには、BindingSource コンポーネントを使用する必要があります。

    注意

    BindingSource コンポーネントにより、バインドのためにすべての IEnumerable 項目が別のリストにコピーされます。

  • ITypedList インターフェイス

    ITypedList インターフェイスを実装するコレクション クラスには、バインドされたコントロールに公開されるプロパティの順序とセットを制御する機能があります。

    注意

    GetItemProperties メソッドを実装したときに、PropertyDescriptor 配列が null でない場合、配列の最後のエントリが、項目の別のリストであるリスト プロパティを示すプロパティ記述子になります。

  • ICustomTypeDescriptor インターフェイス

    ICustomTypeDescriptor インターフェイスを実装するクラスは、そのクラス自体に関する動的な情報を提供します。 このインターフェイスは ITypedList に似ていますが、リストではなくオブジェクトに使用されます。 このインターフェイスは、基になる行のスキーマを反映するために DataRowView で使用されます。 ICustomTypeDescriptor の単純な実装は、CustomTypeDescriptor クラスによって提供されます。

    注意

    ICustomTypeDescriptor を実装する型へのデザイン時のバインドをサポートするには、その型が IComponent も実装し、フォーム上にインスタンスとして存在する必要があります。

  • IListSource インターフェイス

    IListSource インターフェイスを実装するクラスを使用すると、リスト以外のオブジェクトでリストベースのバインドが可能になります。 IListSourceGetList メソッドを使うと、IList を継承していないオブジェクトからバインド可能なリストを返すことができます。IListSourceDataSet クラスによって使用されます。

  • IRaiseItemChangedEvents インターフェイス

    IRaiseItemChangedEvents インターフェイスを実装するクラスは、IBindingList インターフェイスも実装するバインド可能なリストです。 このインターフェイスを使用すると、現在の型で ItemChanged 型の ListChanged イベントを発生させるかどうかを RaisesItemChangedEvents プロパティによって示すことができます。

    注意

    データ ソースが前述のプロパティからリストへのイベント変換を提供し、BindingSource コンポーネントとやり取りする場合は、IRaiseItemChangedEvents を実装する必要があります。 実装していない場合、BindingSource によってプロパティからリストへのイベント変換も実行されるため、パフォーマンスが低下します。

  • ISupportInitialize インターフェイス

    ISupportInitialize インターフェイスを実装するコンポーネントでは、プロパティの設定と相互に依存するプロパティの初期化にバッチ最適化を利用します。 ISupportInitialize には、次の 2 つのメソッドがあります。

    • BeginInit は、オブジェクトの初期化の開始を通知します。

    • EndInit は、オブジェクトの初期化の終了を通知します。

  • ISupportInitializeNotification インターフェイス

    ISupportInitializeNotification インターフェイスを実装するコンポーネントは、ISupportInitialize インターフェイスも実装します。 このインターフェイスにより、他の ISupportInitialize コンポーネントに初期化の完了を通知できます。 ISupportInitializeNotification インターフェイスには、次の 2 つのメンバーが含まれます。

    • IsInitialized は、コンポーネントが初期化されているかどうかを示す boolean 値を返します。

    • Initialized は、EndInit が呼び出されたときに発生します。

  • INotifyPropertyChanged インターフェイス

    このインターフェイスを実装するクラスは、プロパティ値のいずれかが変更されたときにイベントを発生させる型です。 このインターフェイスは、コントロールのプロパティごとに変更イベントを持つパターンを置き換えるように設計されています。 BindingList<T> で使用する場合、ビジネス オブジェクトによる INotifyPropertyChanged インターフェイスの実装が必要です。BindingList`1 によって、PropertyChanged イベントが ItemChanged 型の ListChanged イベントに変換されます。

    注意

    バインドされたクライアントとデータ ソース間のバインドで変更通知を発生させるには、バインドされたデータ ソースの型で INotifyPropertyChanged インターフェイスを実装するか (推奨)、バインドされた型の propertyNameChanged イベントを提供します。ただし、この両方を行うことはできません。

コンポーネント作成者が実装するインターフェイス

以下のインターフェイスは、Windows フォーム データ バインディング エンジンが使用するように設計されています。

  • IBindableComponent インターフェイス

    このインターフェイスを実装するクラスは、データ バインディングをサポートするコントロール以外のコンポーネントです。 このクラスは、このインターフェイスの DataBindings プロパティと BindingContext プロパティを使用して、コンポーネントのデータ バインディングとバインド コンテキストを返します。

    注意

    コンポーネントが Control を継承している場合は、IBindableComponent インターフェイスを実装する必要はありません。

  • ICurrencyManagerProvider インターフェイス

    ICurrencyManagerProvider インターフェイスを実装するクラスは、そのコンポーネントに関連付けられたバインドを管理する独自の CurrencyManager を提供するコンポーネントです。 カスタムの CurrencyManager には、CurrencyManager プロパティからアクセスできます。

    注意

    Control を継承するクラスでは、BindingContext プロパティによってバインドが自動的に管理されるので、ICurrencyManagerProvider の実装が必要になることはほとんどありません。

Windows フォームがサポートするデータ ソース

これまで、データ バインディングは、データベースに格納されているデータを利用するために、アプリケーション内で使用されてきました。 Windows フォームのデータ バインディングを使用すると、データベースのデータや他の構造体のデータ (配列やコレクションなど) にもアクセスできます。ただし、特定の最小要件を満たしている必要があります。

バインド先の構造体

Windows フォームでは、単純なオブジェクト (単純バインディング) から、ADO.NET データ テーブルなどの複雑なリスト (複合バインディング) まで、さまざまな構造体へのバインディングが可能です。 単純バインディングの場合、Windows フォームでは、単純なオブジェクトのパブリック プロパティへのバインドがサポートされます。 Windows フォームのリストベースのバインディングでは、通常、オブジェクトが IList インターフェイスまたは IListSource インターフェイスをサポートしている必要があります。 また、BindingSource コンポーネントを通じてバインドする場合は、IEnumerable インターフェイスをサポートしているオブジェクトにもバインドできます。

次に示すのは、Windows フォームでバインドできる構造体の一覧です。

  • BindingSource

    BindingSource は、最も一般的な Windows フォーム データ ソースです。これは、データ ソースと Windows フォーム コントロールとの間のプロキシとして機能します。 BindingSource の一般的な使用パターンは、コントロールを BindingSource にバインドし、BindingSource をデータ ソース (たとえば、ADO.NET データ テーブルやビジネス オブジェクト) にバインドするという使い方です。 BindingSource には、データ バインディングのサポートを有効にし、そのレベルを改善するためのサービスが用意されています。 たとえば、DataGridViewComboBox などの Windows フォーム リストベース コントロールでは、IEnumerable データ ソースへのバインディングが直接はサポートされていませんが、BindingSource を通じてバインドすることで、そのシナリオを有効にすることができます。 その場合は、BindingSource によってデータ ソースが IList に変換されます。

  • 単純なオブジェクト

    Windows フォームでは、Binding 型を使って、オブジェクトのインスタンスのパブリック プロパティに対するデータ バインディング コントロール プロパティがサポートされています。 また、Windows フォームでは、リストベース コントロールのバインディングもサポートされています (BindingSource が使われている場合のオブジェクト インスタンスに対する ListControl など)。

  • 配列またはコレクション

    データ ソースとして機能させるにはそのリストが IList インターフェイスを実装している必要があります (たとえば、Array クラスのインスタンスである配列など)。 配列の詳細については、「方法: オブジェクトの配列を作成する (Visual Basic)」を参照してください。

    一般に、データ バインディング用のオブジェクトのリストを作成する際には、BindingList<T> を使用する必要があります。 BindingList は、IBindingList インターフェイスのジェネリック バージョンです。 IBindingList インターフェイスは、双方向のデータ バインディングに必要なプロパティ、メソッド、およびイベントを追加することで、IList インターフェイスを拡張します。

  • IEnumerable

    Windows フォーム コントロールは、BindingSource コンポーネントを介してバインドされている場合、IEnumerable インターフェイスのみをサポートしているデータ ソースにバインドできます。

  • ADO.NET データ オブジェクト

    ADO.NET には、バインディングに適したさまざまなデータ構造体が用意されています。 これらのオブジェクトは、それぞれに複雑さが異なります。

    • DataColumn

      テーブルは複数の列で構成されるため、DataColumnDataTable の重要な構成要素です。 各 DataColumn には、列に保持されるデータの種類を決定する、DataType プロパティがあります (たとえば、自動車の情報が格納されたテーブル内の自動車メーカー名など)。 開発者は、コントロール (TextBox コントロールの Text プロパティなど) をデータ テーブル内の列に単純バインドすることができます。

    • DataTable

      DataTable は、ADO.NET でのテーブル (行と列を含む) の表現です。 データ テーブルには、2 つのコレクションが含まれます。1 つは DataColumn です。これは、特定のテーブル内のデータ列を表します (最終的に、そのテーブルに入力できるデータの種類はこれによって決まります)。もう 1 つは DataRow です。これは、特定のテーブル内のデータ行を表します。 開発者は、データ テーブルに格納されている情報にコントロールを複雑バインドすることができます (データ テーブルに対する DataGridView コントロールのバインディングなど)。 ただし、DataTable にバインドすると、テーブルの既定のビューにバインドすることになります。

    • DataView

      DataView は、フィルター処理や並べ替えが可能な、単一のデータ テーブルのカスタム ビューです。 データ ビューは、複合バインド コントロールによって使用されるデータ "スナップショット" です。 開発者は、データ ビュー内のデータに単純バインドや複雑バインドを行うことができます。ただし、随時更新されるクリーンなデータ ソースではなく、データの "静止画" にバインドするようなものであるという点に注意してください。

    • DataSet

      DataSet は、データベース内のデータのテーブル、リレーションシップ、および制約のコレクションです。 開発者は、データセット内のデータに対して単純バインドまたは複雑バインドを行うことができます。ただし、DataSet の既定の DataViewManager にバインドされるという点に注意してください (次の箇条書きを参照してください)。

    • DataViewManager

      DataViewManager は、DataSet 全体のカスタム ビューです。DataView と似ていますが、これにはリレーションシップが含まれます。 DataViewSettings コレクションを使用すると、特定のテーブルに対する DataViewManager のすべてのビューについて、既定のフィルターや並べ替えオプションを設定することができます。

データ バインディングの種類

Windows フォームでは、単純バインディングと複合バインディングの 2 種類のデータ バインディングを利用できます。 それぞれに異なる利点があります。

データ バインディングの種類 説明
単純データ バインディング データセット テーブル内の列の値など、1 つのデータ要素にバインドするコントロールの機能。 単純データ バインディングは、TextBox コントロールや Label コントロールなどのコントロールで一般的に使われる種類のバインディングです。これらのコントロールでは通常、1 つの値のみが表示されます。 実際には、コントロールのどのプロパティもデータベース内のフィールドにバインドできます。 Visual Studio では、この機能に対する広範なサポートが用意されています。

詳細については、「データの移動」と「単純バインド コントロールを作成する (Windows フォーム .NET)」を参照してください。
複合データ バインディング 複数のデータ要素、一般的にはデータベース内の複数のレコードにバインドするコントロールの機能。 複合バインディングは、リストベース バインディングとも呼ばれます。 複合バインディングをサポートするコントロールの例には、DataGridViewListBox、および ComboBox の各コントロールがあります。 複合データ バインディングの例については、「方法: Windows フォームの ComboBox または ListBox コントロールをデータにバインドする」を参照してください。

ソース コンポーネントのバインディング

データ バインディングを単純化するために、Windows フォームでは、データ ソースを BindingSource コンポーネントにバインドしてから、コントロールを BindingSource にバインドできます。 BindingSource は、単純バインディングまたは複合バインディングのシナリオで使用できます。 いずれの場合も、BindingSource はデータ ソースとバインドされたコントロールの間の媒介として機能し、変更通知、通貨管理などのサービスを提供します。

データ バインディングを使う一般的なシナリオ

ほぼすべての商用アプリケーションで、通常はデータ バインディングによってある種類のデータ ソースから別の種類のデータ ソースに読み取られた情報を使用します。 次のリストに、データの表示および操作の方法としてデータ バインディングを使用する最も一般的なシナリオをいくつか示します。

シナリオ 説明
レポート レポートは、印刷された文書でデータを表示および集計する柔軟な方法を提供します。 データ ソースの選んだコンテンツを画面またはプリンターに出力するレポートを作成することはよくあります。 一般的なレポートには、リスト、請求書、および概要などがあります。 項目はリストの列として並べられ、サブ項目が各リスト項目に分類されますが、データに最も適したレイアウトをユーザーが選ぶ必要があります。
データ エントリ 大量の関連データを入力したり、ユーザーに情報の入力を求めたりする場合は、データ エントリ フォームを使用する方法が一般的です。 ユーザーは、テキスト ボックス、オプション ボタン、ドロップダウン リスト、およびチェック ボックスを使用して、情報を入力したり、オプションを選択したりできます。 情報は送信され、入力された情報に基づく構造を持つデータベースに格納されます。
マスター/詳細リレーションシップ マスター/詳細アプリケーションは、関連データを表現するための形式の 1 つです。 具体的には、2 つのデータ テーブルと、それらを結合する関係があります。典型的なビジネスの例では、"顧客" テーブルと "注文" テーブルがあり、それらの間には、顧客とそれに対応する注文を結合する関係があります。 2 つの Windows フォーム DataGridView コントロールを使ったマスター/詳細アプリケーションの作成について詳しくは、「方法: Windows フォームの 2 つの DataGridView コントロールを使用してマスター/詳細形式のフォームを作成する」を参照してください
参照テーブル 別の一般的なデータ表示/操作シナリオに、テーブル ルックアップがあります。 多くの場合、より大きなデータ表示の一部として、ComboBox コントロールを使用してデータを表示および操作します。 重要な点は、ComboBox コントロールで表示されるデータは、データベースに書き込まれるデータとは異なることです。 たとえば、食料品店から入手できる項目を表示する ComboBox コントロールがあり、製品の名前 (パン、牛乳、卵) を表示するとします。 しかし、データベース内での情報の取得を容易にしたり、データベースを正規化したりするには、ある注文の特定の項目に関する情報を項目番号 (#501、#603 など) で格納する必要がある場合があります。 そのため、フォームの ComboBox コントロールにある食料品項目の "わかりやすい名前" と、注文に表示される該当する項目番号との間には暗黙的なつながりがあります。 これがテーブル ルックアップの本質です。 詳細については、「方法: Windows フォーム BindingSource コンポーネントを使用してルックアップ テーブルを作成する」を参照してください。

関連項目