Prism + SPREAD for WPFで動的にViewを読み込む

今回は、以前にご紹介したMVVM(Model-View-ViewModel)フレームワークのPrism上で「SPREAD for WPF(スプレッド)」を使用する例をさらにパワーアップして、Prismの主要機能である「DI コンテナ」と「Region / Navigation」そして「Module」を利用するサンプルをご紹介します。

  1. 今回使用するPrismの機能
  2. 作成するサンプルの概要
  3. メインプロジェクト(Shell)の作成
  4. モジュールプロジェクト(Module)の作成
  5. おわりに

Prismの概要やPrismを使ったプロジェクトを作成するために必要なPrism Template Packのインストール方法については、前回の記事でご紹介しているので、ご参考にしていただければと思います。


1. 今回使用するPrismの機能

MVVMパターンのアプリケーション開発を支援するPrismには多くの便利な機能が用意されていますが、今回は、次の4つの機能を使って簡単なサンプルを作成します。

  • ViewModel の実装を補佐してくれる機能
  • アプリケーション全体で使用できるDIコンテナ機能
  • 名前付き表示領域を管理するRegion / Navigation機能
  • DLLによるプラグイン実装をサポートするModule機能

この中の「DIコンテナ」機能は、「Region / Navigation」と「Module」の機能を利用する際に欠かせないものです。

ここで簡単に用語について説明しておきます。

  • Shell:Moduleを読み込むWindow(またはWindowが含まれているプロジェクト)
  • Module:Shell内のWindowに配置するViewを含んだDLL(またはプロジェクト)
  • Region:Viewの配置先となるWindow内のContentControl
  • Navigation:Region にViewを追加・削除する操作
  • View:WindowまたはUserControl

Prismの詳細については、下記をご参照ください。

Prismのホームページとサンプル

ホームページ:http://prismlibrary.github.io/
サンプル:https://github.com/PrismLibrary/Prism-Samples-Wpf

【メモ】

今回使っている「Region / Navigation」の機能がPrismサンプル
 17-BasicRegionNavigation

に実装されているので、一度ご確認いただければと思います。

2. 作成するサンプルの概要

サンプル

サンプルの機能

サンプルに配置している各ボタンの機能は、次のとおりです。

  • Viewの表示:SPREADが配置されているViewを表示します
  • Viewの非表示:SPREADが配置されているViewを非表示にします
  • データの保存:データをXMLファイルに保存します
  • 行の追加:新しい行を末尾に追加します
  • 行の削除:カレント行を削除します
  • 変更の確定:データソースに加えられた変更内容を確定します
  • 変更の破棄:データソースに加えられた変更内容を破棄して元に戻します

最初の3つのボタンはShellのWindowに配置されており、残りの4つのボタンはModuleのUserControlにSPREADと一緒に配置されています。

サンプルの構造

概要

モデルに含まれるデータソースは、前回と同じでコード(Code)、製品名(Name)、価格(Price)の3つのフィールドからなる製品データ一覧です。

SPREADは、前回はShellのMainWindow(Window)上に配置しましたが、今回は別のModuleに含まれているViewA(UserControl)上に配置します。そして、ShellのプロジェクトからModuleのプロジェクトを参照(Module機能)し、Module内のViewAをShell内のMainWindow内に表示(Region / Navigation機能)します。

つまり、親であるMainWindow内に子となるViewAを配置して、さらにその中に孫のSPREADを配置する形になります。

また、Shell内にあるデータソースをModule内のSPREADに連結するために、PrismのDIコンテナ機能を使ってデータソースのインスタンスをコンテナに登録し、それをModule内のViewModelのコンストラクタで取得しています。

MVVMの構成は次のようになっています。

  • モデル:ProductModel.cs(Shell)
  • ビュー:MainWindow.xaml(Shell)とViewA.xaml(Module)
  • ビューモデル:MainWindowViewModel.cs(Shell)とViewAViewModel.cs(Module)

なお、今回のサンプルでも次の点を考慮して、できるだけ「イベントハンドラとコードビハインドよりもXAMLに記述する」ようにしています。

  • テスト容易性
  • 再利用性
  • 可読性

3. メインプロジェクト(Shell)の作成

プロジェクトの生成

Prismのテンプレートを使ってShellとなるメインプロジェクトを作成します。

  1. Visual Studioを起動する
  2. [スタートページ]-[新しいプロジェクト]の検索欄に「prism」と入力する
  3. 表示されたリストから「Prism Blank App (WPF) C#」を選択する
  4. プロジェクトの保存先とプロジェクト名(SpreadWPF_Prism2)を指定する
  5. 表示された[PRISM PROJECT WIZARD]で「Unity」を選択して[CREATE PROJECT]ボタンをクリックする
  6. メニューの[ビルド]-[ソリューションのリビルド]を選択する

以上の操作でPrismのShellプロジェクトが自動的に生成されます。

【メモ】

Prismのテンプレートを利用するには、あらかじめPrism Template Packをインストールしておく必要があります。

※インストールの手順については、前回の記事をご参照ください。

モデル(ProductModel)の作成

先ほど作成したプロジェクトに「ProductModel」という名前のモデル用のクラスを追加し、下記のコードを記述します。

ここでは、データソースとしてDataSetを使うことで、データを保持するXMLファイルへの保存と読込を簡素化しています。また、GetProductsメソッドは、外部からDataTableを取得するために用意しています。

ビュー(MainWindow)の作成

MainWindow

次の手順でViewsフォルダ内のMainWindowビューを変更します。各プロパティの設定内容については、下のXAMLを参照してください。

  1. Windowの各プロパティを設定します
  2. デフォルトで追加されているGridを削除します
  3. DockPanelを貼り付けます
  4. DockPanelのプロパティを設定します
  5. DockPanel内にStackPanelを貼り付けます
  6. StackPanelのプロパティを設定します
  7. StackPanel内に3つのButtonを貼り付けます
  8. 各Buttonのプロパティを設定します
  9. StackPanelの下にContentControlを貼り付けます
  10. ContentControlのプロパティを設定します

以上の操作を行ってMainWindowのXAMLを次のようにします。

左端のButton:
CommandParameterに設定した”ViewA”を引数にしてMainWindowViewModelNavigateCommandメソッドを呼び出します。その結果、この後で作成するModuleのViewAContentControlに読み込まれ、MainWindow上に表示されます。

中央のButton:
空文字を引数にしてMainWindowViewModelNavigateCommandメソッドを呼び出すことで、表示したViewAを削除します。

右端のButton:
MainWindowViewModelSaveCommandメソッドを呼び出して、ProductModel内のDataSetの内容をXMLファイルに保存するためのものです。

【注記】

SPREADのライセンス作成とプロジェクトへ参照を追加するため、GcSpreadGridコントロールをContentControlの下に貼り付け、すぐに削除しておきます。

ビューモデル(MainWindowViewModel)の作成

ビューモデルは、Prismのテンプレートが自動で生成するViewModelsフォルダにあるMainWindowViewModel.csに次のように記述します。

ビューモデルに実装する機能は、次のとおりです。

  • Navigationを実現するために必要なIRegionManagerの取得
  • Region / Navigation機能を実行するNavigateCommandとNavigateメソッド
  • データをXMLファイルに保存するSaveCommandとSaveDataメソッド

なお、MainWindowViewModelのコンストラクタで取得しているIRegionManagerは、Prismが自動的に設定します。

Shell機能の実装

Shellの基本機能を実装するために、Shell側で行う重要なステップがもう1つあります。

【メモ】

ここに追加するコードは、SpreadWPF_Prism2プロジェクト(Shell)にNavigationプロジェクト(Module)を参照設定している必要があります。
そのため、ここに記載している内容は、次の「4. モジュールプロジェクト(Module)の作成」を行った後で実装してください。

ここでは、次の3つのメソッドを追加することで、Shellの重要な機能を実装します。

  • OnStartupメソッド:データを保持しているXMLファイルの読み込み
  • RegisterTypesメソッド:モデル(ProductModel)で取得したデータのインスタンスのコンテナへの登録
  • ConfigureModuleCatalogメソッド:Module(NavigationModule)の読み込み

具体的には、プロジェクトに自動生成されるApp.xaml.csに次のように記述します。


4. モジュールプロジェクト(Module)の作成

プロジェクトの追加

次の手順で、PrismテンプレートのModuleプロジェクトをソリューションに追加します。

  1. Visual Studioのメニューで[ファイル]-[追加]-[新しいプロジェクト]を選択する
  2. 表示されたリストから「Prism Module (WPF) 」を選択する
  3. プロジェクト名(Navigation)を指定する
  4. Moduleプロジェクトの追加
  5. [OK]ボタンをクリックする
  6. メニューの[ビルド]-[ソリューションのリビルド]を選択する

ビュー(ViewA)の作成

MainWindow

次の手順でViewsフォルダ内のViewAビューを変更します。各プロパティの設定内容については、下のXAMLを参照してください。

  1. UserControlの各プロパティを設定します
  2. デフォルトで追加されているGrid内のTextBlockを削除します
  3. GridのRowDefinitionsとColumnDefinitionsを設定します
  4. GcSpreadGridを貼り付けます
  5. GcSpreadGridのプロパティを設定します
  6. GcSpreadGridの下にButtonを4つ貼り付けます
  7. 各Buttonのプロパティを設定します

以上の操作を行ってViewAのXAMLを次のようにします。

SPREAD本体:
SPREADのItemsSourceプロパティにビューモデルのProductsプロパティを連結し、SelectedItemプロパティにはSelectedProductプロパティを連結しています。これにより、モデルのデータがSPREADにデータ連結され、SPREAD上のカレント行が移動するたびにその行の情報がビューモデルに伝えられます。

SPREADの列:
SPREADの第1列から第3列に対応するデータのフィールド名を設定してデータ連結を可能にします。また、第1列はTextCellTypeに、第3列はNumberCellTypeに設定します。

Button:
4つのButtonCommandには、それぞれ該当するコマンド名をバインドします。これによって、ボタンをクリックしたときに目的の動作が実行されます。

ビューモデル(ViewAViewModel)の作成

ViewModelsフォルダ内のViewAViewModel.csに次のように記述します。

【メモ】

Prismでは、ModelViewのクラスでINotifyPropertyChangedインタフェースの機能を拡張したBindableBaseクラスを継承します。
これにより、PropertyChangedEventHandlerとOnPropertyChangedを実装する必要がなくなるので、プロパティの記述がとてもシンプルになります

Moduleのビューモデルに実装する機能は、次のとおりです。

  • コンテナを経由したデータ(DataTable)の取得
  • データを保持するDataTable型のProductsプロパティ
  • SPREADのカレント行をビューと共有するSelectedProductプロパティ
  • 行追加の処理を行うAddCommandとAddメソッド
  • 行削除の処理を行うDeleteCommandとDeleteメソッド
  • DataTable(DataSet)への変更を確定するAcceptCommandとAcceptメソッド
  • DataTable(DataSet)への変更を破棄するRejectCommandとRejectメソッド

Module機能の実装

Prismが自動生成するNavigationModule.csファイルを下のように変更します。

RegisterTypesメソッドに追加したコードによって、このModuleがコンテナに登録されてNavigation操作が可能になります。

以上でサンプルアプリケーションの完成です。


作成したサンプルは以下で公開しています。SPREAD for WPF 2.0J SP3で作成されています。


5. おわりに

次回は、PrismのInteractionRequest機能を使ってViewから別のダイアログをポップアップするサンプルをご紹介する予定です。

製品Webサイトでは、SPREAD for WPF 2.0Jのデモアプリケーションを公開しています。グリッド系コントロールの基本機能はもちろん、Excelライクな操作性や自由度の高い表レイアウトなど、数多くの機能が用意されていますので、以下より是非お試しください。

\  この記事をシェアする  /