はじめに
この記事では、Windows Presentation Foundation(WPF)とPresentation Modelパターンを使用して、複数の編集可能な行項目をコレクションにバインドする高度な技法を紹介します。この記事の内容は、読者がWPFデータバインディングの技法、およびオブジェクト指向UIライブラリで一般的に使用されるデザインパターンに関する基本的知識をお持ちであることを前提としています。まず記事全体で使用するサンプルアプリケーションの概要を紹介し、その後、このアプリケーションにPresentation Modelパターンを適用してUI層とビジネスロジック層を分離する方法を示します。最後に、実際にPresentation ModelをXAMLコントロールにバインドして、複数の編集可能な行項目を持つ動的UIを作成するために必要なWPF固有の細かい処理についても説明します。
動的ユーザーインターフェイス
「複数の編集可能な行項目を持つ動的ユーザーインターフェイス」の意味をわかりやすく示すために、まず、それとは対照的な静的インターフェイスの例として、Webベースのアカウント登録フォームの場合を考えてみましょう。このユースケースでは、ユーザーに個人情報の入力を求めるフォームを表示し、ユーザーから得られた情報を、それに対応する(ユーザープロファイルを表す)ビジネスオブジェクトまたはデータベーステーブルにマッピングします。ユーザーがフォームに入力して送信した個人情報はサイトに保存され、サイトから確認の電子メールが送信されるとユースケースは完了します。
この場合、UIとデータ検証のコードが適切であるとすれば、このフォームを作成した開発者は必要な情報を前もって正確に把握していて、それゆえ、ユーザーによる不正なデータの入力を防止するための制約を課すことができたと考えられます。したがって、このインターフェイスは静的と表現できます。要求した情報を検証するためのパラメータは事前に判明しており、そのUIがアプリケーションのインスタンスごとに変化することはありません。
これと対比して、今度は日々の経費を管理するための取引記録を考えてみましょう。このフォームでは、ユーザーが入力する支出項目の件数は一定せず、1件の場合もあれば20件の場合もあるでしょう。このようなアプリケーションの開発では、安全策をとって、あらかじめ定めたかなり多数の(通常1日に予想される入力件数を超える行数の)空の行項目を表示することも考えられますが、これはエレガントとは言い難い方法です。それよりも優れたもう1つの方法は、UIに表示する行項目を必要に応じて新たに生成することです。
情報の正確な量(項目の件数)を開発者が前もって知ることはできないので、これは動的なUIです。動的なUIはより直観的で、すっきりした画面を実現でき、そのときどきの必要性に応じて項目数を調整することで、ユーザーが目下の作業に集中しやすい環境を実現します。
サンプルアプリケーション: Expenses.NET
この記事でサンプルアプリケーションとして使用する「Expenses.NET」は、まさにそのような動的UIを持つ取引記録アプリケーションです(図1)。このアプリケーションでは、各週の日々の支出を明細項目として記録できます。起動すると、UIの中央に、1つのListViewItemを含んだListViewが表示されます。
このListViewItemには、その週内の特定の日を選択するためのComboBoxと、支出の説明を入力するためのTextBox、金額入力用のもう1つのTextBox、および明細項目を追加するためのボタンと既存の項目を削除するためのボタンが含まれています。
それぞれのListViewItemに表示されるデータは、ExpenseLineItemという名前のビジネスオブジェクトによって保持されます。ExpenseLineItemクラスは、上記の各コントロールに対応するプロパティを外部に公開しており、また、WPFのバインディングフレームワークと連係して動作するためにINotifyPropertyChangedインターフェイスを実装しています。ListView自体のデータはExpenseSheetという別のビジネスオブジェクトによって保持されます。このExpenseSheetには、ExpenseLineItemを要素として持つObservableCollectionが格納されています。
Presentation Modelパターン
Expenses.NETの中核を成すのはPresentation Modelパターン(図2)です。名高い4人組のデザインパターン本(『Design Patterns: Elements of Reusable Object-Oriented Software』)にはこのパターンに関する章は含まれていませんが、Martin FowlerのWebサイトでは、「Enterprise Application Architecture」セクションの1ページを割いて、このパターンが詳しく解説されています。Fowlerの言葉を借りれば、このパターンは「インターフェイスで使用されているGUIコントロールに依存せずにプレゼンテーションの状態と振る舞いを表す」方法です。これはMVCモデルや、UIコントロールライブラリで一般的に使用されている類似のパターンとどう違うのだろうと疑問に思われるかもしれませんが、実のところ本質的には違いはありません。
このパターンはコントロールをアプリケーションレベルで抽象化したもので、ビジネスオブジェクトからのデータに基づいてユーザーインターフェイス全体の状態を制御します。これらのビジネスオブジェクトの各プロパティは、コントロールのプロパティに対応しています。ここで取り上げている例では、WPFデータバインディングが接着剤としての役割を担い、これらのプロパティの同期を保持します。この抽象化は特定のプラットフォームに固有のものではなく、ASP.NETのWebアプリケーションやモバイルデバイスなどを対象とするその他のUIでも再利用可能なので、非常に有効です。