今回は、MVVM(Model-View-ViewModel)フレームワークのPrismを使って、親画面に配置された「SPREAD for WPF(スプレッド)」のアクティブ行に対応した明細情報を表示するSPREADを子画面としてポップアップするサンプルをご紹介します。
1. 今回使用するPrismの機能
MVVMパターンのアプリケーション開発を支援するPrismの多くの機能の中で、今回は、次の5つの機能を使って簡単なサンプルを作成します。
- ViewModel の実装を補佐してくれる機能
- アプリケーション全体で使用できるDIコンテナ機能
- 名前付き表示領域を管理するRegion / Navigation機能
- DLLによるプラグイン実装をサポートするModule機能
- ViewModelとViewの間で通信を行うInteractionRequest機能
今回のサンプルで子画面をポップアップするときに利用しているのが、5番目の「InteractionRequest」の機能です。親画面のSPREADのアクティブ行を特定する情報を子画面に渡すためにこの機能を使っています。
ここで簡単に用語について説明しておきます。
- Shell:Moduleを読み込むWindow(またはWindowが含まれているプロジェクト)
- Module:Shell内のWindowに配置するViewを含んだDLL(またはプロジェクト)
- Region:Viewの配置先となるWindow内のContentControl
- Navigation:Region にViewを追加・削除する操作
- View:WindowまたはUserControl
Prismの詳細については、下記をご参照ください。
ホームページ:http://prismlibrary.github.io/
サンプル:https://github.com/PrismLibrary/Prism-Samples-Wpf
【メモ】
今回使っている「InteractionRequest」の機能がPrismサンプルの
28-CustomRequest
に実装されているので、ご確認いただければと思います。
2. 作成するサンプルの概要
サンプルの機能
サンプルに配置している各ボタンの機能は、次のとおりです。
- Viewの表示:SPREADが配置されているViewを表示します
- Viewの非表示:SPREADが配置されているViewを非表示にします
- 明細の表示:明細画面をポップアップします
- 戻る:子画面を閉じて親画面に戻ります
最初の2つのボタンはShellのWindow
に配置されており、3つ目のボタンはModule内の親画面用のUserControl
にSPREADと一緒に配置されています。最後のボタンは、Module内の明細画面用のUserControl
にSPREADと一緒に配置されています。
データの構成
モデルに含まれるデータソースは、親画面のSPREADに表示されるOutline
テーブルと、明細画面のSPREADに表示されるDetail
テーブルから構成されています。本来、これらのテーブルは、データベース内の正規化された複数のテーブルから作成されますが、ここでは直接これらのテーブルを作成しています。
各テーブルのフィールドは、次のようになっています。
- Outline:Class(分類)+Quantity(数量)+Amount(金額)
- Detail:Code(コード)+Name(品名)+Price(単価)+Class(分類)+Quantity(数量)+Amount(金額)
サンプルの構造
ShellのMainWindow(Window
)には、別プロジェクトのModuleに含まれているViewA(UserControl
)が配置され、そのViewA上にはOutlineテーブルを表示するSPREADがあります。また、同じModule内にあるDetail(UserControl
)にはDetailテーブルを表示するSPREADが配置されており、ViewAからポップアップされます。
また、Shell内にあるデータソースをModule内の2つのSPREADに連結するために、PrismのDIコンテナ機能を使ってデータソースのインスタンスをコンテナに登録し、それをModule内のViewAViewModelとDetailViewModelのコンストラクタで取得しています。
MVVMの構成は次のようになっています。
- モデル:ProductModel.cs(Shell)
- ビュー:MainWindow.xaml(Shell)とViewA.xaml(Module)およびDetail.xaml(Module)
- ビューモデル:MainWindowViewModel.cs(Shell)とViewAViewModel.cs(Module)およびDetailViewModel.cs(Module)
このサンプルでは、次の点を考慮して、できるだけ「イベントハンドラとコードビハインドよりもXAMLに記述する」ようにしています。
- テスト容易性
- 再利用性
- 可読性
3. メインプロジェクト(Shell)の作成
ShellとなるメインプロジェクトのSpreadWPF_Prism3
は、次の手順で作成します。
- プロジェクトの生成
- モデル(ProductModel)の作成
- ビュー(MainWindow)の作成
- ビューモデル(MainWindowViewModel)の作成
- Shell機能の実装
これらの手順に先立ってPrismのテンプレートである「Prism Template Pack」を開発環境にインストールしておく必要があります。
以上についての具体的な内容は、下記の2つの記事をご参照ください。
モデル(ProductModel)の作成
メインプロジェクトのほとんどの内容は、上記の記事「Prism + SPREAD for WPFで動的にViewを読み込む」と同じですが、ProductModelの内容だけは異なっているので、ここで紹介しておきます。
ここでは、データソースとして前述の2つのDataTableを含むDataSetを使っています。また、外部からこのDataSetを取得するためにGetSalesメソッドを用意しています。
4. モジュールプロジェクト(Module)の作成
- プロジェクトの追加
- ビュー(ViewA)の作成
- ビューモデル(ViewAViewModel)の作成
- ユーザーコントロールの追加
- ビュー(Detail)の作成
- ビューモデル(DetailViewModel)の作成
- Module機能の実装
プロジェクトの追加
次の手順で、PrismテンプレートのModuleプロジェクトをソリューションに追加します。
- Visual Studioのメニューで[ファイル]-[追加]-[新しいプロジェクト]を選択する
- 表示されたリストから「Prism Module (WPF) 」を選択する
- プロジェクト名(Navigation)を指定する
- [OK]ボタンをクリックする
- メニューの[ビルド]-[ソリューションのリビルド]を選択する
ビュー(ViewA)の作成
次の手順でViews
フォルダ内のViewA
ビューを変更します。各プロパティの設定内容については、下のXAMLを参照してください。
- UserControlの各プロパティを設定します
- デフォルトで追加されているGrid内のTextBlockを削除します
- GridのRowDefinitionsを設定します
- GcSpreadGridを貼り付けます
- GcSpreadGridのプロパティを設定します
- GcSpreadGridの下にButtonを貼り付けます
- Buttonのプロパティを設定します
以上の操作を行ってViewA
のXAMLを次のようにします。
SPREAD本体:
SPREADのItemsSource
プロパティにビューモデルのOutline
プロパティを連結し、SelectedItem
プロパティにはSelectedProduct
プロパティを連結しています。これにより、モデルのデータがSPREADにデータ連結され、SPREAD上のアクティブ行が移動するたびにその行の情報がビューモデルに伝えられます。
SPREADの列:
SPREADの第1列から第3列に対応するデータのフィールド名を設定してデータ連結を可能にします。また、第2列と第3列はNumberCellTypeに設定します。
Button:
Button
のCommand
にはShowDetailCommand
をバインドします。これによって、ボタンをクリックしたときに明細画面がポップアップされます。
ビューモデル(ViewAViewModel)の作成
ViewModels
フォルダ内のViewAViewModel.cs
に次のように記述します。
ViewAのビューモデルに実装する機能は、次のとおりです。
- コンテナを経由したデータ(DataSet)の取得
- データを保持するDataTable型のOutlineプロパティ
- SPREADのアクティブ行をビューと共有するSelectedProductプロパティ
- 明細画面をポップアップするShowDetailCommandとShowDetailメソッド
- 明細画面との通信を行うShowDetailRequest(InteractionRequestクラス)
ユーザーコントロールの追加
次の手順で、PrismテンプレートのユーザーコントロールをNavigationプロジェクトに追加します。
- Visual Studioのソリューションエクスプローラーで[Navigation]プロジェクトを右クリックする
- コンテキストメニューから[追加]-[新しい項目]を選択する
- 表示されたリストから「Prism UserControl (WPF) 」を選択する
- View名(Detail.xaml)を指定する
- [追加]ボタンをクリックする
ビュー(Detail)の作成
次の手順でViews
フォルダ内のDetail
ビューを変更します。各プロパティの設定内容については、下のXAMLを参照してください。
- UserControlの各プロパティを設定します
- デフォルトで追加されているGrid内のTextBlockを削除します
- GridのRowDefinitionsを設定します
- GcSpreadGridを貼り付けます
- GcSpreadGridのプロパティを設定します
- GcSpreadGridの下にButtonを貼り付けます
- Buttonのプロパティを設定します
以上の操作を行ってDetail
のXAMLを次のようにします。
SPREAD本体:
SPREADのItemsSource
プロパティにビューモデルのSales
プロパティを連結しています。これにより、モデルのデータがSPREADにデータ連結され、親画面のSPREAD上のアクティブ行に対応した明細情報が表示されます。
SPREADの列:
SPREADの第1列から第4列に対応するデータのフィールド名を設定してデータ連結を可能にします。また、第3列と第4列はNumberCellTypeに設定します。
Button:
Button
のCommand
にはCloseCommand
をバインドします。これによって、ボタンをクリックしたときに明細画面が閉じられます。
ビューモデル(DetailViewModel)の作成
ViewModels
フォルダ内のDetailViewModel.cs
に次のように記述します。
Detailのビューモデルに実装する機能は、次のとおりです。
- コンテナを経由したデータ(DataSet)の取得
- データを保持するDataView型のSalesプロパティ
- 明細画面を閉じるCloseCommandとCloseInteractionメソッド
- 親画面との通信に使う INotificationn型のNotificationプロパティ
- インタラクションの終了処理に使用するAction型のFinishInteractionプロパティ
Module機能の実装
Prismが自動生成するNavigationModule.cs
ファイルを下のように変更します。
RegisterTypesメソッドに追加したコードによって、このModuleがコンテナに登録されてNavigation操作が可能になります。
以上でサンプルアプリケーションの完成です。
作成したサンプルはこちらで公開しています。SPREAD for WPF 2.0J SP4で作成されています。NuGetパッケージを復元して実行してください。
5. おわりに
製品Webサイトでは、SPREAD for WPF 2.0Jのデモアプリケーションを公開しています。グリッド系コントロールの基本機能はもちろん、Excelライクな操作性や自由度の高い表レイアウトなど、数多くの機能が用意されていますので、以下より是非お試しください。