Prismの全機能を使おうと思ったらModule使ったりとか結構だるいです。でも「Regionで画面区切って画面遷移できる機能とかは使いたい。」と思いました。
思考錯誤して出来たのでメモっておきます。
NuGetからのインストール
Prism.UnityExtensionsをNuGetからダウンロードします。
Shellの作成
MainWindowをさくっと消して、Viewsフォルダをきって、そこにShellという名前のWindowを作ります。そして中身にRegionを定義します。
<Window x:Class="WpfApplication11.Views.Shell"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:prism="http://www.codeplex.com/prism"Title="Shell"Height="300"Width="300"><Grid><ContentControl prism:RegionManager.RegionName="Main" /></Grid></Window>
ViewModelLocatorを使ってViewModelを差し込みたいので、IViewを実装しておきます。
using Microsoft.Practices.Prism.Mvvm; using System.Windows; namespace WpfApplication11.Views { /// <summary>/// Shell.xaml の相互作用ロジック/// </summary>publicpartialclass Shell : Window, IView { public Shell() { InitializeComponent(); } } }
Bootstrapperの作成
Bootstrapperを作ります。ポイントは、ShellにViewModelを差し込むためのViewModelLocatorの設定をInitializeShellでやってるところです。ここでやらないと、RegionManagerにRegionが生成される前にViewModelが生成されたりして厄介なのです…。
あと、Views名前空間にあるViewを全てobject型としてコンテナに登録しておきます。これはRegionManager内で使うためです。
最後に、ViewModelLocationProviderに、ViewModelの型の生成をUnityで行うように生成処理を差し替えています。
using Microsoft.Practices.Prism.Mvvm; using Microsoft.Practices.Prism.UnityExtensions; using Microsoft.Practices.Unity; using System.Linq; using System.Windows; using WpfApplication11.Views; namespace WpfApplication11 { publicclass Bootstrapper : UnityBootstrapper { protectedoverride DependencyObject CreateShell() { returnthis.Container.Resolve<Shell>(); } protectedoverridevoid InitializeShell() { ViewModelLocator.SetAutoWireViewModel(this.Shell, true); // ここでViewModelを差し込む ((Shell)this.Shell).Show(); } protectedoverridevoid ConfigureContainer() { base.ConfigureContainer(); // Viewを全てobject型としてコンテナに登録しておく(RegionManagerで使うため)this.Container.RegisterTypes( AllClasses.FromLoadedAssemblies().Where(t => t.Namespace.EndsWith(".Views")), getFromTypes: _ => new[] { typeof(object) }, getName: WithName.TypeName); // ViewModelLocatorでViewModelを生成する方法をUnityで行うようにする ViewModelLocationProvider.SetDefaultViewModelFactory(t => this.Container.Resolve(t)); } } }
Regionに表示するViewを作成
Views名前空間にUserControlでMainPageを作ります。中身はとりあえず表示されればいいので適当です。
<UserControl x:Class="WpfApplication11.Views.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"mc:Ignorable="d"d:DesignHeight="300"d:DesignWidth="300"><Grid><TextBlock Text="MainPage" /></Grid></UserControl>
本番では、こいつにViewModelLocatorを使ってVMを差し込んで使いますが、ここでは表示されることを確認したいだけなので、やってません。
ShellViewModelの作成
ShellのViewModelを作ります。コンストラクタでIRegionManagerを受け取って、MainPageを表示するように指示しています。
using Microsoft.Practices.Prism.Regions; namespace WpfApplication11.ViewModels { publicclass ShellViewModel { public ShellViewModel(IRegionManager rm) { rm.RequestNavigate("Main", "MainPage"); } } }
Startup処理を作成
App.xamlのStartupUriを消してStartupイベントを書きます。イベント内ではBootstrapperを作ってRunしてるだけです。
using System.Windows; namespace WpfApplication11 { /// <summary>/// App.xaml の相互作用ロジック/// </summary>publicpartialclass App : Application { privatevoid Application_Startup(object sender, StartupEventArgs e) { var b = new Bootstrapper(); b.Run(); } } }
実行
実行するとMainPageが画面に表示されます。Module機能使わないでRegionを使うことが出来ました。めでたしめでたし。