episode: 2 ~ WPFのフレームワーク決まってますか?迷ってますか?Prismを選択してもらっていいですか? ~

← episode: 1 ~ WPF は MVVM フレームワークとともに~

episode: 1 では使用するフレームワークを決定しませんでした。
episode: 1 を書いていた頃は【MVVM Light Toolkit】を第一候補に考えていたんですが、調べていくと MVVM Light Toolkit には MVVM の最低限の機能は含まれているが、応用的な仕組みは使用者自身で作成する必要がある… 的な印象を受ける情報が多く、日本語での情報も最初に調べた頃からほとんど増えていない印象も受けたので、第一候補を【Prism】に変更して再度調べました。

Prism は最初からサポートしている機能が多いこと、日本語での情報も 1 年前よりは増えたような印象を持ったことで、最終的に使用する MVVM フレームワークを Prism に決定。
やはり、よく利用しそうな仕組みが最初から組み込まれていて楽できそう!と思ったことが 1 番の理由ですw

尚、この記事は Visual Studio 2017 Community Edition で .NET Framework 4.6以上 と C# を使用して 、WPF アプリケーションを MVVM パターンで作成するのが目的で、C# での基本的なコーディング知識を持っている人が対象です。

Prism の導入メリット

Prism を使用して MVVM パターンのアプリケーションを作成すると、同じようなコードを何度も繰り返して書かざるを得ない苦行から解放されるのはもちろん、下図のように多種の UI 部品を動的に読み込んだり切り替えたりするような画面の作成も可能になります。

動的 UI 部品の読込機能を標準機能のみで実装しようとした場合、コードビハインドへの記述が必要になる状況も多く発生しそうですが、Prism を使用すると、ViewModel 内への記述のみで完結することができ又、作成された各コンポーネント間の関係はユニットテストを組み込みやすい疎結合を保って作成されます。

動的 UI 部品読込機能を自分で作り込むことも可能でしょうが、その機能を備えたライブラリが既に存在していているのに、車輪の再発明をする必要はないと思っています。(業務で使用する場合等は導入が難しいかもしれませんが、Microsoft謹製だからと金の御旗を掲げて詰め寄ることができるかもしれませんw 事実、Prism 5.0 は現時点でも Microsoft からダウンロードできます。)

又、2017年12月からは Xamarin でも WPF の作成が可能になり、Prism は Xamarin もサポートしているため、将来的に Xamarin を使ってみたいと思っているなら、覚えるメリットは十分にあると言えるでしょう。

Prism の基本的な用語

まずは、Prism の最も基本となる用語を紹介します。

Shell(シェル)
シェルとは、モジュールが読み込まれるホスト・アプリケーションを表します。
Windows Form アプリケーションで例えると、スタートアップフォーム(プロジェクト)のようなものと考えてください。
メインウィンドウやスタートアッププロジェクトを指してシェルと呼ぶ場合が多い。
Module(モジュール)
モジュールとは、必要に応じて、独立して開発、テスト、配布することができる、機能単位のパッケージです。
公式サンプルに含まれる多くの例としては、シェル内に読込む View を含んだ DLL プロジェクトです。
Region(リージョン)
View の読込先コンテナコントロールを識別するためのプレークスホルダーです。
xaml ファイルに文字列で指定したコンテナコントロール内に View を読み込んだり、View を切替えたりできます。
Bootstrapper(ブートストラッパー)
某 twitter 社の UI ライブラリと名前が似ていますが、デザインで使用する訳ではなく、さまざまな Prism のコンポーネントとサービスを初期化する用途で使用するクラスです。
Prism の各種初期化を 1 か所で行うために使用します。

上記以外にも必要な用語はありますが、ここでは 4 つだけ覚えば OK です。極端なことを言えば、上記以外の用語は現時点では無視しても構いません。機能の理解に必要な用語が出てきた場合は、その都度紹介していく予定です。

Prism の公式サンプル

以降は Prism の公式サンプルを使用しますが、あらかじめ Prism をインストールしていなくても、おそらく動くのではないかと思っています。
もし、Prism のインストールが必要な場合は、episode: 1 を参照してください。

episode: 1 を書いていた頃は、公式サンプルの存在を知らなかったので、Prism でどんなことができるかを調べるのにかなり苦労しましたが、Prism の公式サンプルは 1 つ 1 つが非常に小さくシンプルで、Prism が提供する個々の機能を簡単に理解することができる優秀なサンプルが 29 種類も含まれています。

まずは、Prism の公式サンプル をリンク先の GitHub からダウンロードしてください。(GitHub からのソース取得はここでは紹介しません)
以下が全サンプルの概要です。

1.Bootstrapper and the Shellブートストラッパーとシェルのサンプル。
2.Regionsリージョンのサンプル。
3.Custom RegionsStackPanel を Region として使用するためのアダプターを作成する。(最初から理解する必要はなし。必要に応じて参照すれば良い)
4.View DiscoveryView Discovery によって View を自動的に注入する。(View をシェルのコードビハインドから注入する。コードビハインドに何も記述したくない場合はとりあえず見なくても OK)
5.View InjectionView Injection を使って手動で View を動的に追加する。(ボタンの Click イベントでロードするサンプル。イベントハンドラはコードビハインドに記述)
6.View Activation/DeactivationView を動的にアクティベートしたりディアクティベートする。(イベントハンドラはコードビハインドに記述)
7.Modules – AppConfigApp.config ファイルを使用してモジュールをロードする。
7.Modules – Codeソースコードからモジュールをロードする。
7.Modules – Directoryディレクトリ配下のモジュールを自動的にロードする。
7.Modules – LoadManualIModuleManager を使って手動でモジュールをロードする。(イベントハンドラはコードビハインドに記述)
8.ViewModelLocatorViewModelLocator を使用した View と ViewModel の関連付け。
9.ViewModelLocator – Change ConventionViewModelLocator のネーミング規約を変更する。
10.ViewModelLocator – Custom RegistrationsView と VewiModel の組み合わせを手動で登録する。
11.UsingDelegateCommandsDelegateCommand と DelegateCommand<T> を使う。
12.UsingCompositeCommandsコンポジットコマンドを使って複数のコマンドを一つのコマンドとして呼び出す。(「全てを保存」ボタン)
13.IActiveAware Commandsアクティブな場合にのみコマンド(CompositeCommands)を実行する。
14.UsingEventAggregatorIEventAggregator を利用して ViewModel – ViewModel 間でデータをやり取りする。
15.EventAggregator – FilteringEventsEventAggregator に登録する際、受け取るイベントを絞り込む。
16.RegionContextモジュール内の View に Region を定義して View を切替える。(シェルだけでなくモジュールにもリージョンの定義が可能)
17.BasicRegion Navigation基本的なリージョンナビゲーション(画面遷移)。
18.Navigation Callbackナビゲーションが完了した時に通知を受け取る。
19.Navigation ParticipationINavigationAware を使って View 切替え前後に動作を設定する。
20.Navigate to existing ViewsView 切替え時の View の生存期間をコントロールする。(同じ View を再利用するか新規に作成するか)
21.Passing ParametersView/ViewModel から別の View/ViewModel にパラメータを渡す。
22.Confirm/cancel NavigationIConfirmNavigationReqest インターフェイスを使って「確認」「取消」のメッセージボックスを表示する。
23.Controllng View lifetimeIRegionMemberLifetime を使ってメモリーから Views を自動的に取り除く。
24.Navigation Journal同一 Region 内の View 切替え履歴を管理する。(「戻る」「進む」ボタン)
25.Interactivity – NotificationRequestInteractionRequest を使ってメッセージ画面を表示する。(MessageBox クラスは不使用)
26.Interactivity – ConfirmationRequestInteractionRequest を使って確認用ダイアログを表示する。(「OK」「Cancel」ボタン)
27.Interactivity – Custom ContentInteractionRequest でダイアログに独自に作成した View を設定する。
28.Interactivity – Custom RequestInteractionRequest でポップアップした View と値をやり取りする。
29.Interactivity – InvokeCommandActionコントロールのイベントにコマンドをバインドする。

公式サンプル『14-UsingEventAggregator』

まずは、ダウンロードした公式サンプル内の『14-UsingEventAggregator』直下にあるソリューションを開きます。
Visual Studio が起動したら、ソリューションエクスプローラーのソリューションを右クリックして、[NuGet パッケージの復元]又は、[ソリューションの NuGet パッケージの管理]をクリックして NuGet から必要なパッケージを復元すると必要なコンポーネントが NuGet から取得されます。

後はビルドして実行するとメインウィンドウ(シェル)が表示されます。
ここで説明した『14-UsingEventAggregator』以外のプロジェクトも同様の実行することができます。

公式サンプル『14-UsingEventAggregator』のソリューション構成

左図は『14-UsingEventAggregator』のソリューション構成です。

ModuleA プロジェクト
シェルの左側に読み込まれる View を含むモジュール。
ModuleB プロジェクト
シェルの右側に読み込まれる View を含むモジュール。
UsingEventAggregator プロジェクト
このソリューションのシェル。
UsingEventAggregator.Core プロジェクト
EventAggregator で受け渡しするクラス定義を含むプロジェクト。

シェルのソース

アプリケーションのエントリポイントとなる、App.xaml.cs です。

Application クラスの OnStartup イベント内で生成した Bootstrapper が Prism アプリケーションの起点になります。

この Bootstrapper クラスに Prism の各種初期化処理を実装します。
1 ~ 11 行目までは Prism Template で自動生成されます。
13 ~ 18 行目のオーバーライドしたメソッドでアプリケーションに読み込むモジュールを定義しています。

このようにアプリケーション内で使用したいモジュールは Bootstrapper 内で定義することで読み込まれますが、ソースコードへ記述する方法だけでなく、App.config 内に定義したり、指定したディレクトリ内を検索して見つかったモジュールを自動で登録することもできます。

実際の運用を考えると、ディレクトリ内に配置して自動登録する方法が最も適していると管理人は思いますが、ここでは説明しません。
ディレクトリ内のモジュールを自動登録する方法は、Prism 公式サンプルの『07-Modules – Directory』にあるので必要な場合は個別に参照してください。

4 行目は、Prism を使用するための XML 名前空間です。
5行目は、View と ViewModel の関連付けにファイル名を使用するかを設定しています。(Trueに設定すると、View の名前が Views.MainWindow である場合、ViewModel は ViewModels.MainWindowViewModel に自動的に関連付けられます)

11 行目と 12 行目はモジュールを読み込むためのリージョン名の定義です。
ここで定義したリージョン名はモジュール側にも記述します。

以上がシェルの設定で、引き続いてモジュール側のソースを紹介します。

モジュールのソース

サンプル内にはモジュールが 2 つありますが、基本的な内容は同じため、ModuleA のみを例に挙げます。
モジュールには必ず IModule インタフェースを継承したクラスを含める必要があり、モジュール自身の初期化やシェルとの関連付け等を行います。

10 ~ 13 行目でシェルに設定したリージョンに読み込む View を定義しています。

Prism を使用した UI 部品の動的読込は、上で紹介したソースを書くだけで、後の動作は全て Prism にお任せで動いてくれます。予想に反して少ないコーディング量だったのではないでしょうか。
※ サンプルには EventAggregator を使用した ViewModel – ViewModel 間の通信も含まれていますが、今回は触れません。

紹介したサンプルが No.1 からではなく、飛ばして No.14 を紹介したのは、UI 部品の動的読込についてはこのサンプルが全てだからです。No.14 が理解できていれば、No.14 以前のサンプルはそれぞれの機能が単機能単位に書かれているだけなので、特に悩むことなく理解できると考えたからです。

Prism で UI 部品の動的読込を行うために最低限必要なことは以上ですが、今回の記事はここまでとして、次回は実際にアプリケーションを作成する記事になる予定です。

episode: 3 ~ Re: ゼロから始める Prism 生活 ~ →

あわせて読みたい

コメントを残す

%d人のブロガーが「いいね」をつけました。