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

この記事は Visual Studio 2017 Community Edition で .NET Framework 4.6 と C# を使用して 、WPF アプリケーションを MVVM パターンで作成するのが目的で、C# での基本的なコーディング知識を持っている人が対象です。
2020/7/4 追記
2020 年度版の WPF 用 MVVM フレームワークを紹介するエントリ を公開しました!
MVVM パターンを利用した WPF 開発
あえて説明するまでも無いと思いますが、MVVM とは Model、View、View Model の頭文字で、特に UI への入出力を実装するためのデザインパターンです。

fig.1 MVVM パターン概要図
MVVMパターンについての解説とかはここに書かない(書けない)ので、@ITの「MVVMパターンの常識 ― 「M」「V」「VM」の役割とは?」等を読んで下さい。
ちなみに、上で紹介してる @IT の記事は国産 MVVM フレームワーク 『Livet』の作者 尾上雅則さんが書かれた記事で、管理人的には非常に分かり易く、ソフトウェアアーキテクチャを検討する際の参考にもなる良い記事だと思っているので、理解出来るまで何度も読み返すと良いと思います。
この連載(予定)内では、MVVM を適用する際、View のコードビハインドには何も書かない原理主義を目標に進めていきたいと思っています。
原理主義が絶対!とか主張したい訳ではありませんが、管理人の場合どうせ勉強するなら理想を求めたいし、何か縛りがあった方が萌えるタイプなんで原理主義で突き進みたいと思ってます。
そして WPF アプリを MVVM で作るために MVVM フレームワークは必須と言えるでしょう。(必須だと言うのは管理人の私見で、無くても作れます)
WPF 公開当初から Visual Studio には MVVM 実装のための仕組みは最低限しか組み込まれていないため、MVVM フレームワーク無しで開発しようとすると、非常に単調なコードを何度も書くことを強要されます。
もし、仕事で WPF の開発案件の募集が管理人に来て MVVM フレームワーク無しだと言われたら、裸足で逃げたくなるレベルです。
単調で生産意義も特に無いコードを残業してでも大量に書きたいと言うドMな人は別かもしれませんがw
Java 等の案件では普通にフレームワークを使うのに Microsoft 製品での開発だとフリーのライブラリ等を使いたがらない現場も多い不思議な業界なんでしょうがない。(管理人の体感ですが、あくまでも私見です)
実際の募集案件だと MVVM フレームワーク無しで開発、なんて状況があるかもしれませんがここでは当然フレームワークを使います。
なので、フレームワークやライブラリ無しで MVVM を実装する方法を探している人が必要とする情報はここにはありません。
MVVMフレームワークについて調べたまとめを以下に紹介します。
Livet
国産の MVVM フレームワークで、作者は上で紹介した @IT の記事を書かれた尾上雅則さん。
Ver.2.0の開発予定は発表されてるようですが、2015年8月から放置状態のようで、Livet は 2015年8月に発表された Ver.1.3 が最終バージョンと考えるしかないでしょう。
一応、WPF 4.0、4.5 には対応しているようなので使用するには問題ないかもしれませんが、Visual Studio への対応は 2010 までですし、.NET Framework 4.6 以降への対応もされてないため、現状では選択肢から外れるのは妥当と言えるでしょう。
国産のフレームワークらしく、MVVM へのきめ細かい仕組みが実装されているようで(実際に使用していませんし、詳しく調べていません)、本来なら第一候補にしたいフレームワークですが、開発が止まっているため止む無く対象外としました。
やはり前回書いたように、将来的には UWP や Xamarin を使ってみたいと思っているので、やはり将来性が無いフレームワークは対象外としました。
Livet 2.0 以降がリリースされています。
ReactiveProperty のメンテナーでもあるかずきさんが尾上さんから引き継いでメンテナンスされることになったようで、プロジェクトテンプレート等も併せてリリースされている為、現時点では候補として調査・検討するフレームワークに復権したと言えるでしょう。
MVVM light toolkit
Visual Studio の拡張機能としてインストールすると MVVM のプロジェクトテンプレートが選択できるようになり、シンプルな MVVM プロジェクトが作成されるフレームワーク。
海外製ライブラリではよく見る「足らないものは自作してね」的なスタンスのフレームワークのようです。(名称に Light が入ってますし)
Visual Studio のメニューから [ツール] – [拡張機能と更新プログラム] を選択してキーワードに【mvvmlight】と入力すると見つかる【MVVM light for VS2017】をインストールします。

fig.2 VS にインストールする MVVM light toolkit 拡張機能
インストールが完了して、新しいプロジェクトの作成を選択すると、MVVM light toolkit のプロジェクトテンプレートが選択できるようになるので、【MvvmLight (WPF 451)】を選択します。

fig.3 MVVM light toolkit のプロジェクトテンプレート
作成されるプロジェクトには、Model、ViewModel、Designフォルダが作成されて、それぞれのフォルダ内には MVVM を構成するためのクラスも作成されます。
又、プロジェクトの新規作成ダイアログで .NET Framework のバージョンを 4.5.1 以外に変更しても、作成されるプロジェクトは 4.5.1 になります。
使用する NET Framework バージョンを変更したい場合は、作成後にプロジェクトのプロパティから変更する必要があります。
注意点として、作成したプロジェクトの [Nuget パッケージの管理] を開くと、【CommonServiceLocator】の最新版がリリースされていると通知されますが、最新版に更新するとビルドエラーが発生します。
.NET Standard 1.0 に対応したのが原因のようで、MVVM light toolkit のサイト【NET Standard 1.0 Support】に回避方が載っています。
自分的にはとりあえず困っていないので Ver.1.3 のままで続行します。(間違えて新しいバージョンへ更新してしまって戻したい場合は、1.3 へバージョンダウンすればOK)
MVVM light toolkit のプロジェクトを作成するとビルドエラーが発生する
こんな失敗は自分だけかもしれませんが、かなり長期間ハマったので書いておきます。
結論から言うと、MVVM light toolkit のプロジェクトを作成する前に、Visual Studio のオプションで [プロジェクトおよびソリューション] – [作成時に新しいプロジェクトに保存] がチェックされている必要があります。

fig.4 Visual Studio のオプション
このチェックが Off の状態で MVVM light toolkit プロジェクトを作成してしまうと、意味が分からないエラーに悩まされることになりますが、上記赤枠項目の初期値が Off に設定されているのが原因です。
通常使用する場合は、チェックされていようがチェックされてなかろうが特に困ることはありませんが、MVVM light toolkit のプロジェクトを作成する場合は、かなり困った状況でした。
当然と言えば当然でしょうが、このチェックが Off のままでプロジェクトを作成すると MVVM light toolkit のコアライブラリは Nuget から復元されない状態で作成されます。
自動生成されたソースファイルを何でも良いので開くと、ビルドエラーが発生してる状態なので、Nuget からライブラリの MVVMlight をインストールします。
インストールの途中で、ソースファイルの上書きを何度か聞かれますが、上書きしようがしまいがエラーは消えませんでした。
具体的には App.xaml で以下のようなエラーが発生しました。
- 名前 “ViewModelLocator” は名前空間 “clr-namespace:プロジェクト名.ViewModel” に存在しません。
- すべてのディクショナリ エントリにキーが関連付けられている必要があります。
- IDictionary に追加されるすべてのオブジェクトは、Key 属性またはオブジェクトに関連する別の型のキーを保持している必要があります。
このエラーを解消する方法はあるのかもしれませんが、何分 WPF 開発自体も初めてだったのでどうすれば良いか分からず、海外の情報まで調べても解消方法はわかりませんでした。
パッケージ復元込みのテンプレートからプロジェクトを作成したのが今回初めての経験だったため、かなりハマりました。
もし同様な状況で困っている場合は、上記のオプションをチェックすると、プロジェクト作成時に保存先を指定しなければならなくなるので、保存先を指定して作成するだけで嘘のようにエラーが無いプロジェクトが作成されるようになります。
Prism
Prism は元々 Microsoft の patterns & practices で開発された複合アプリケーションを作成するためのフレームワークで、現状は MVP の方々が中心となって管理されているようです。
元々、MVVM をサポートするためのライブラリというより、モジュールを組み合わせて1つのアプリケーションを作成するためのフレームワークとして開発されていたみたいで、Ver.4から MVVM をサポートするクラスがいくつか追加されて今に至ってるようです。
Prism をインストールするには MVVM light toolkit と同じく、メニューから [ツール] – [拡張機能と更新プログラム] を選択してキーワードに【prism】を入力して見つかる【Prism Template Pack】をインストールします。

fig.5 Visual Studio にインストールする Prism 拡張機能
インストールが完了するとPrismのプロジェクトテンプレートが選択できるようになります。

fig.6 Prism のプロジェクトテンプレート
見て分かる通り、WPF のアプリを作成するには一覧の上から1番目の Prism Blank App (WPF) 又は、3番目の Prism Module (WPF) が選択肢になります。
上から3番目の Prism Module (WPF) はアプリの部品を作成するためのテンプレートで、クラスライブラリプロジェクトが作成されるので、exe 形式のプロジェクトを作成したい場合は、1番上の 【Prism Blank App (WPF)】を選択します。
プロジェクトテンプレートを選択して OK ボタンを Click すると、DIコンテナを選択する画面が表示されます。

fig. 7 Prism の DI コンテナ選択画面
ここで好きなコンテナを選択しますが、どれを選択していいか分からない場合は、とりあえず【Unity】を選択してください。この連載でも DI コンテナは Unity を使用しています。
自分も現状ではあまり詳しく調べてませんが、WPF について調べてた時に【Unity】ってキーワードもよく見かけたので、情報を探し易いような気がします。
その辺りについては又、改めて調べてから記事にしたいと思っています。
MVVM light toolkit の場合は、パッケージが Nuget から自動的に復元されてすぐに作成が開始出来ますが、Prism の場合はパッケージを復元してくれないようで、最初はビルドエラーが発生していて、Nuget からパッケージを自分でインストールする必要があります。

fig. 8 Prism のプロジェクト新規作成直後
プロジェクトの右クリックメニューから [Nuget パッケージの管理] を選択して【参照】タブから【prism】と入力して検索します。
検索結果の一覧から【Prism.Wpf】を選択してインストールするとビルドエラーが消えます。

fig. 9 Prism のプロジェクトを作成するための Nuget コンポーネント
ビルドエラーが消えると、WPF アプリが作成できるようになります。
MVVM light toolkit と違って、Views、ViewModels フォルダのみが作成されていて、フォルダ内にはMainWindow クラスが作成されます。
又、MVVM light toolkit を紹介した前章の [作成時に新しいプロジェクトに保存] 設定で発生するエラーは Prism の場合、チェックの有無に関わらずテンプレートを選択すると保存先の設定が強制されるため発生しません。
最終的に使用するフレームワークは保留
代表的な MVVM フレームワークを紹介し終わって、本来であればここで使用するフレームワークを決めるのが通常の流れだと思いますが、現時点ではとりあえず保留します。
現時点では、決定できる程フレームワークをいじっていないことと、この後数回は MVVM とあまり関係ない内容の記事になりそうな予定、と言うのが主な理由です。
記事のネタに使うつもりのアプリも鋭意製作中なので、作成してる間にフレームワークも色々触って記事にしたいと思っているので、少々お待ちください。(誰も待ってないでしょうが…)
2回続けて読み物風の記事になりましたが、次回は技術ネタらしい記事にしたいと思ってます。
2020/7/4 追記
2020 年度版の WPF 用 MVVM フレームワークを紹介するエントリ を公開しました!
このエントリを公開して約 2 年が経って結論を保留のままにしているのを思い出しましたw
現時点(2019/9/27)で Prism の紹介エントリは episode: 17 まで進み、このサイトのメインコンテンツと言える連載になっているので、当然ですが最終的に使用するフレームワークは Prism に決定しています。
Prism は各画面を DLL プロジェクトへ分割した UserControl で作成でき、作成した UserControl を動的に切り替える事ができるのが一番のメリットと管理人は考えているので、そのような用途のアプリを作成する場合は向いていると言えます。
又、Prism 7.2 からはダイアログを簡単に扱える IDialogService も追加され UserControl で作成したダイアログウィンドウ Prism 7.1 以前より簡単に扱えるようになりました。
そのような構成の WPF アプリケーションを作成したい場合は Prism のインストールをお勧めします!
2019/9/27 追記
次回記事「WPF のフレームワーク決まってますか?迷ってますか? Prism を選択してもらっていいですか?【episode: 2 WPF Prism】」