WPF Prism を使ってみた

はじめに

開発部の前嶋です。

若手プログラマの中には、与えられた環境を使っているだけで、導入しているライブラリ、フレームワークが何を提供しているか、説明できない、という方もいるのではないでしょうか?
特に、開発に途中から参加していて技術選定に関わっていない場合、陥りがちな気がします。
今回はそんな自分自身への戒めの意味も込めて、開発で使用している「Prism」について調べ直しました。

Prism は WPF の MVVM パターンの開発を支援するフレームワークです。
MVVM パターンとは、Model-View-ViewModel の 3つの部分に分割してアプリケーションの設計・実装をする方法で、それぞれの役割を明確にすることによって、開発効率や保守性が向上します。

Prism を使って簡単なアプリを作成し、具体的にどんな機能を提供しているのか確認していきます。
※よく併用される ReactiveProperty の機能は使用せず、純粋に Prism で実装します。

環境
  • Visual Studio 2019
  • .NET Framework 4.8
  • Prism.7.2.0.1422
作成したアプリ

ダイアログを表示するだけのアプリを作成します。ダイアログは、2019年 7月リリースの Prism7.2 より実装方法が変更されたため、使ってみます。

【作成したアプリの仕様】

  • 「Open」ボタン押下で、ダイアログを表示し、親画面からパラメータ(現在時刻)を渡します。
  • ダイアログには親画面から渡されたパラメータを表示します。
  • ダイアログの「Close」ボタン押下でダイアログを閉じ、親画面に実行結果(現在時刻)を返します。
  • 親画面はダイアログから受け取った実行結果を表示します。

【初期表示】

【ダイアログ表示】

【ダイアログ Close】

導入手順

Visual Studio の Marketplace から、Prism Template Pack をインストール

Prism Blank App(WPF) を選択してプロジェクトを作成

プロジェクト名とディレクトリを指定
フレームは .NET Framework 4.8 を選択

DI コンテナは Unity を選択

これでプロジェクトの作成が完了しました。
Prism Template Pack を使用すると、このまま実行するだけで、メインウィンドウが表示されます。

実装

以下のファイルを作成します。

それぞれ Prism でどのように実装されるのか見ていきます。
(App.xaml.cs 以外の .xaml.cs ファイル、App.xaml はテンプレートのままのため割愛します。)

【App.xaml.cs】

Prismで は、View を DI コンテナに登録し、管理しています。
IContainerRegistry を使って DI コンテナに View の登録を行います。今回のアプリでは初期表示する View とダイアログを登録します。
CreateShel() でウィンドウを作成し、RegisterTypes() で View を登録しています。

【MainWindow.xaml】

最初に作成されるウィンドウです。テンプレートのままです。
このウィンドウに View を表示していきます。
App.xaml.cs で登録した View を、RegionManager で指定して表示します。今回は ”ContentRegion” という領域に設定された View を表示します。
prism:ViewModelLocator.AutoWireViewModel に True を設定することで、クラス名に従って View と ViewModel を結びつけることができます。

【MainWindowViewModel.cs】

MainWindow.xaml の ViewModel です。
アプリ起動時の初期表示で表示する View を IRegionManager で設定します。MainWindow.xaml で指定した領域 ”ContentRegion” に Sample.xaml が表示されるように設定しています。
継承している BindableBase は ViewModel の実装の補佐をしています。主に View とのデータバインディング(View と ViewModel の変数の紐づけ)の機能を提供します。

【Sample.xaml】

初期表示で表示する View です。
「Open」ボタンが押下されたら、ViewModel(SampleViewModel.cs) の OpenDialogCommand が実行され、ダイアログが表示されます。
ResultMessage は ViewModel のプロパティと紐づいており、ダイアログから受け取った値を表示します。

【SampleViewModel.cs】

Sample.xaml の ViewModel です。
画面の「Open」ボタン押下時に実行する処理を実装します。DelegateCommand を使うことで、ViewModel のプロパティにメソッドを譲渡し、View から ViewModel のメソッドを呼び出すことができます。
IDialogService はダイアログを開く機能を提供します。SampleDialog.xaml がダイアログとして表示されるようにしています。
ダイアログに渡すパラメーターは、IDialogParameters で設定することができます。今回は時刻を渡しています。

※ 2019年 7月に Prism7.2 がリリースされ、ダイアログの実装方法が変更されました。その影響で、従来の実装で使用していた「INotification」や「IInteractionRequestAware」は廃止となり、IDE では警告が表示されます。

【SampleDialog.xaml】

ダイアログの View です。
prism:Dialog.WindowStyle でスタイルを設定しています。サブウィンドウのサイズ指定を UserControl で指定すると、Window のリサイズに中身(UserControl)が付いてこないため、prism:Dialog.WindowStyle で指定します。
「Close」ボタンが押下されたら、ViewModel(SampleDialogViewModel.cs) の CloseDialogCommand が実行され、ダイアログが表示されます。
Message は ViewModel のプロパティと紐づいており、親画面から受け取った値を表示します。

【SampleDialogViewModel.cs】

SampleDialog.xaml の ViewModel です。
ダイアログは IDialogAware を継承します。
OnDialogOpened メソッドが初期表示時に実行され、親画面からのパラメータを受け取ることができます。画面に表示するプロパティ、Message に受け取った値を代入しています。
ダイアログを閉じるには、RequestClose を使用します。
IDialogResult で親画面に実行結果とパラメータを返すことができます。実行結果の種類には enum が用意されており、今回は「Close」ボタンが押下された場合に ButtonResult.OK を設定し、パラメータに現在時刻を設定しています。

まとめ

今回のアプリでは、Prism の以下の機能を使用しました。

IContainerRegistry DIコンテナにクラスを登録する
ViewModelLocator クラス名に従って View と ViewModel を結びつける
BindableBase View とのデータバインディングの機能を提供
IRegionManager 画面遷移に関する機能を提供
DelegateCommand View から実行された際に指定された処理を呼び出す
IDialogService ダイアログの呼び出し関連の機能を提供
IDialogAware ダイアログ関連の機能を提供

Prism が提供している機能はまだまだありますが、代表的な機能や、新しい機能を選んで使用しました。
画面表示関連や、データバインディングといった、WPF の MVVM パターンで開発するにあたって、必要な機能が揃っていることが分かりました。

普段から使っているものでも、改めて調べてみると勉強になります。分からないことは調べる、当たり前のことですが、意外と出来ていなかったと気づきました。開発に慣れてきた時こそ、今一度きちんと理解出来ているか、振り返ってみることも必要かもしれません。

関連記事

  1. BLEAD-TSHで遊ぼう!【作例集 サイコロ型IoTデバイス編】

  2. Beaconアプリ開発記【その4 画面表示編】

  3. アジャイル ~壁を乗り越える~【第1回 導入編】

  4. BLEAD-TSHで遊ぼう!【作例集 筋トレカウンター編】

  5. 何でこうなるの? 現場で起きた開発回顧録【その1 Ajaxと画面更新】…

  6. ビーコンを活用したキャンペーン事例〜来場者を識別し限定特典を付与〜