Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

PrismのRegionをなるべく仰々しくない方法で使う

$
0
0

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を使うことが出来ました。めでたしめでたし。

f:id:okazuki:20140911224640p:plain


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>