シングルインスタンスを Windows フォームにデータバインドする方法はじめに .NETプラットフォームのデータバインディング機能は強力な開発ツールです。データバインディングとは、簡単に説明すれば、「アプリケーション要素のプロパティを、グラフィカルな表示要素の中の特定要素にリンクすること」です。たとえば、カスタムオブジェクトのプロパティ(従業員オブジェクトの名前プロパティなど)を、Windowsフォームのテキストボックスの データバインディングは開発者にとって新しい概念でありません。アプリケーションの基本的な部分であり、アプリケーションのエンドユーザーと処理ロジックの間で情報をやりとりするための、最も基本的な方法です。多くの場合、これは「力仕事」で行われてきました。手作業でコードを書いて、オブジェクトのプロパティとGUI要素(テキストボックス、データグリッド、チェックボックスなど)の間でデータをマーシャリングしてきました。しかし、.NET Frameworkには、これまでにない豊富な機能が備わっています。特に、アプリケーションでデータバインディングを使うことには、大きな魅力があります。
私の見る限り、データバインディング機能は充分に活用されていません。GUIとアプリケーションオブジェクトとのデータのやりとりを実現するために、膨大なコードを書き続けている開発者をまだよく見かけます。おそらく、.NETで何ができるかを知らないか、データバインディングが水面下でデータをどう管理しているのかを理解していないかの、どちらかでしょう。この記事を読むことで、こうしたハードルを乗り越え、アプリケーションでデータバインディングを使うきっかけにしてほしいというのが、私のねらいです。 データバインディングは広範なテーマなので、この記事で扱うことと扱わないことを、あらかじめ区別しておきます。この記事では、独自のシングルインスタンスオブジェクトをWindowsフォームコントロールにバインディングする方法だけを扱います。Webフォームのバインディングは扱いません。また、独自のコレクションをデータグリッドやドロップダウンボックスといった要素にバインディングする方法も扱いません。ASP.NETのWebフォームに関する開発の大部分が完成しつつあるのは知っていますが、.NET開発者の関心と支持を急速に集めているスマートクライアント開発への準備になるという理由で、Windowsフォームに的を絞ることにしました。 前提 この記事の説明とコード例では、全体を通して同じクラスとWindowsフォームを使用します。コード例を作成するにあたっては、話をわかりやすくするためにシンプルなもの、かつ、皆さんに興味を持ってもらえる程度には複雑なものにするよう心がけました。そこで、 この記事で使用するクラスは、一般的な企業をモデルとして作ったものです。したがって、複雑なビジネスロジックや、別の層の別のクラスに属するデータアクセスは出てきません。説明上、オブジェクトのプロパティにデータが必要な場合は、値をハードコーディングします。オブジェクトを保存する必要がある場合は、単純にファイルにシリアライズします。これも、例を単純化して、データバインディングに専念するためです。 図1 ![]() このクラスのすべてのソースコードを見る場合は、この記事の先頭のダウンロード用リンクを使用してください。ダウンロードファイルには3つのソリューションが含まれており、それぞれこの記事で説明するデータバインディングの種類に対応しています。 具体的なデータバインディングの話に進む前に、ソースコードについていくつか説明しておきます。まず、ダーティフラグ(dirty flag)とその実装方法についてです。ダーティフラグは、オブジェクトのプロパティが違う値に変更されたかどうかを示します。オブジェクトのプロパティに値が設定されるたびに、図2のように、 図2 ![]() 呼び出された 図3 ![]() この記事で使用するフォームが図4です。 図4 ![]() このフォームには、従業員の名前(First Name)、名字(Last Name)、雇用日(Hire Date)、給与(Salary)を表示するテキストボックスがあります。.NET Framework内でデータバインディングがどのようにキャストと変換を行うのかを見てもらうため、 これから説明するアプリケーションの要素について基本的な説明が終わったところで、データバインディングがどのように動作するのかを見ていきましょう。 力仕事のデータバインディング最初に説明するデータバインディングの方法は、私が「力仕事」と名づけた方法です。この方法では、オブジェクトと表示の連結部をすべてハードコーディングし、.NET Frameworkのデータバインディング機能はまったく使用しません。これを基準にすると、.NETが実際にどれくらいのことを行ってくれるのかがよくわかります。この例の全ソースコードは、ダウンロードサンプルの「ManualDataBindingSolution」フォルダの中にあります。 フォームの中には、フォームで使用する 図5 ![]() フォームのコンストラクタの中では、図6のとおり従業員オブジェクトをインスタンス化し、データを設定します。説明の便宜上、値はハードコーディングしています。実際のアプリケーションでは、こうした値はほとんどの場合、ビジネスロジックやデータクラスによって設定されます。 図6 ![]() フォームの 図7 ![]() 図8 ![]() コードを見てわかるとおり、 オブジェクトの値がどのように設定され、その値がどういった経路でオブジェクトからフォームのコントロールに渡されるかを理解したところで、次は、[Save]ボタンがクリックされたときなどに、フォームコントロールの値がオブジェクトにどのようにマーシャリングされるのかを見てみましょう。フォームの値をオブジェクトにマーシャリングするための実際のロジックは図9のとおりです。 図9 ![]() ここでも、データをテキストベースのプロパティから 図10 ![]() すべての値がフォームからオブジェクトに正常にマーシャリングされ、少なくとも1つのプロパティの値が変更されていた場合は、そのオブジェクトがアプリケーションのカレントディレクトリにあるXMLファイルにシリアライズされます。 [Load New Values]ボタンは、データソースから新しい値を入力するなど、現在の 一方向のデータバインディング このシナリオでは、.NET Framworkの機能を使用して、 このソリューションでは、 図11 ![]() このメソッドでは単純に、GUI要素とローカルオブジェクトのプロパティとのデータバインディングを定義しています。バインディングは、コードの243〜244行目のような方法で、それぞれ個別に設定する必要があります。構文は以下のとおりです。 図12 ![]() この構文から、各コントロールが自分用のデータバインディングのコレクションを持っていることがわかります。このコレクションの中で、コントロールの各プロパティがデータバインディングを持つことができます。重要なのは、プロパティはデータバインディングを1つしか持てないという点です。複数割り当てることもできますが、システム引数例外になります。このため、バインディング処理の前に、目的のプロパティにバインディングがあるかどうかをチェックし、あれば削除します。このコードでは239〜241行目でその処理を行っています。 図13 ![]() バインディングを作成する構文(図12の242〜244行目)を見てみましょう。コントロール側のプロパティ( バインディングに使用するコントロール側のプロパティは、バインディングの構文の中で指定するので、他のプロパティにバインディングするのも簡単です。例えば271〜272行目では、チェックボックスの もう1つ注目すべきは、データバインディング機能は自動的に変換を行ってくれることです。これで、 ここで注意してほしいのは、アプリケーションを起動したときに、デフォルトの書式が使用されるという点です。[Hire Date]テキストボックスの場合は、日付と時間が表示されますが、これは意図とは違います。手作業によるデータバインディングの例では、 図14 ![]() 図14が示すとおり、ここでは[Hire Date]テキストボックスのバインディング(イベントハンドラの登録も含む)を定義してから、そのバインディングを実際のコントロールに割り当てています。これは、バインディングがコントロールに割り当てられた時点で、バインディング機能が自動的にデータソースから値を取得するためです。したがって、図15のように、バインディングの定義と割り当てを一気に行ってからハンドラを割り当てた場合は、書式設定が適用されません。 図15 ![]() データバインディングの動作は、アプリケーションを実行したり、テキストボックスの値を変更したり、[Save]ボタンをクリックしたりすることで確認できます。[Save]の しかし、この方法ではデータフローは一方向(フォームからオブジェクト)のみです。オブジェクトのプロパティの値が変更された場合、フォームには変更が反映されません。このことは[Load New Values]ボタンをクリックすると確認できます。このボタンの データバインディングが一方向だけの機能であるならば、「なぜフォームに初期値が読み込まれたのか」と疑問に思うでしょう。答えはこうです。データバインディングが割り当てられると、データバインディング機能はプロパティの現在の値を参照しますが、ある方法を使わない限り、コントロールがオブジェクトから値を取得するのはこの1回限りになります。以降も継続的に値が取得されるようにするには、次の「上級レベルのデータバインディング」で説明する変更を加えます。 上級レベルのデータバインディングここでは、データバインディングの学習の総仕上げとして、オブジェクトとフォームの間で双方向の通信を可能にし、どちらかを変更するともう一方も変更される方法を説明します。この方法は、オブジェクトとGUIコントロールの間で双方向の通信を行うので、ほとんどの場合で、この方法を使用することになるでしょう。前出の例で見たとおり、一方向(基本的にはフォームからオブジェクト)だけの通信を使用すると、オブジェクトがフォーム以外から変更されたときに矛盾が起こります。双方向の通信を行うためには、データバインディング機能に、オブジェクトのプロパティがいつ変更されたのかを知らせる必要があります。このソリューションのソースコードは、ダウンロードサンプルの「TwoWayDataBindingSolution」フォルダに収録されています。 コントロールのプロパティとデータソースのプロパティとの間でバインディングを定義すると、データバインディング機能は自動的にデータソース上で「プロパティ名+Changed」という名前のイベントを探します。イベントが見つかると、データバインディング機能はこのイベントのハンドラを用意し、該当プロパティの値が変更されたときに通知を受け取るようにします。したがって、 図16のコードでは、必要なイベントを宣言するため、 図16 ![]() 図17 ![]() オブジェクトがフォームに変更を通知できるようになったので、[Save]ボタンの 図18 ![]() まとめ.NET Frameworkのデータバインディングには、多くの機能があります。初期のMicrosoftのツールセットからはずいぶん進歩しました。この記事では、完全な手作業から、コントロールとカスタムオブジェクトのプロパティとの間の双方向通信まで、さまざまなレベルでのデータバインディングを取り上げました。また、.NET Frameworkのデータバインディング機能のイベントモデルを利用して、デフォルトの書式設定処理を変更する方法も示しました。 著者紹介Luther Stanton(Luther Stanton)
Intellinet Corporation(本社:ジョージア州アトランタ)のプリンシパルコンサルタント。Intellinet社は、米国南東部では唯一、5種類のMicrosoft Gold Certified Partnerに認定されており、アプリケーションの開発およびインフラストラクチャのコンサルティングサービスを行っている。オブジェクト指向技術と独自の方法を用いて企業の.NETシステムを構築している。同社独自の方法は、最先端の技術を組み合わせた最善の開発方法である。
著者は、妻Heidiとともにジョージア州ローカストグローブに在住。Microsoftベースのアプリケーション開発に8年、.NET開発に3年のキャリアを持つ。最近は主に、方法論的デプロイメントとエンタープライズアーキテクチャのコンサルティングおよび構築に従事している。メールアドレスはluthers@intellinet.com。 最新トップニュース
|
|