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> public partial class 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 { public class Bootstrapper : UnityBootstrapper { protected override DependencyObject CreateShell() { return this.Container.Resolve<Shell>(); } protected override void InitializeShell() { ViewModelLocator.SetAutoWireViewModel(this.Shell, true); // ここでViewModelを差し込む ((Shell)this.Shell).Show(); } protected override void 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 { public class 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> public partial class App : Application { private void Application_Startup(object sender, StartupEventArgs e) { var b = new Bootstrapper(); b.Run(); } } }
実行
実行するとMainPageが画面に表示されます。Module機能使わないでRegionを使うことが出来ました。めでたしめでたし。