読者です 読者をやめる 読者になる 読者になる

熊小屋日誌

Windows 10 UWPやXamarin, Python、mbed/NetMF/Arduino/Edison, Azureなどぼちぼちと。たまにPCや勉強会、セミナーなどの話題も

Prism 6 for UWP(3)~DIコンテナのUnityの利用

第1回では、ViewとViewModelの対応をアプリの初期化メソッドOnInitializeAsyncで登録しました。

App.xaml.cs

namespace PrismApp1
{
    public partial class App : PrismApplication
    {

     ...

        protected override Task OnInitializeAsync(IActivatedEventArgs args)
        {
            ViewModelLocationProvider.Register(typeof(MainPage).ToString(), () => new MainPageViewModel(NavigationService));
            ViewModelLocationProvider.Register(typeof(UserInputPage).ToString(), () => new UserInputPageViewModel(NavigationService));

            return base.OnInitializeAsync(args);
        }
    }
}

この方法は、画面数が増えてくるとViewとViewModelの対応を維持しづらくなる問題があります。 これを解決するために、依存性を管理するDIコンテナのUnityを使います。

NuGetでパッケージ追加

Prism.Unityパッケージを追加します。

App.xaml、App.xaml.csの修正

App.xaml.csで以下を変更します。

  • PrismUnityApplicationを継承する。

  • OnInitializeAsyncメソッドを削除する。

using Prism.Mvvm;
using Prism.Unity.Windows;
using Prism.Windows;
using PrismApp1.ViewModels;
using PrismApp1.Views;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;

namespace PrismApp1
{
    public partial class App : PrismUnityApplication
    {
        public App() : base()
        {
            InitializeComponent();
        }

        protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
        {
            NavigationService.Navigate("Main", null);
            return Task.FromResult<object>(null);
        }
    }
}

App.xamlも同様にPrism.Unity.Windows.PrismUnityApplicationを継承します。

<prism:PrismUnityApplication
    x:Class="PrismApp1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PrismApp1"
    xmlns:prism="using:Prism.Unity.Windows" 
    RequestedTheme="Light">

</prism:PrismUnityApplication>

ViewModelはUnityを利用しない場合と同じで、ViewModelBaseを継承して、 コンストラクタの引数でINavigationService navigationServiceを受け取ります。

コードではViewとViewModelの関係を登録していませんが、 実行するとNavigateメソッドで画面遷移することが分かります。

ViewModelLocatorによるViewとViewModelの対応付け

ViewとViewModelの対応付けは

Views/MainPage ⇒ ViewModels/MainPageViewModel

Views/UserInputPage ⇒ ViewModels/UserInputPageViewModel

のように、Navigate("[Name]", ...)による画面遷移でViews/[Name]Pageが使用されて、 この画面にViewModels/[Name]PageViewModelが対応づけられます

このViewとViewModelの対応付けはViewModelLocatorによっておこなわれますが、 Views/[Name]PageにおいてViewModelLocatorのAutoWiredViewModel添付プロパティを Trueに設定することで機能します。

MainPage.xaml

<prism:SessionStateAwarePage
    x:Class="PrismApp1.Views.MainPage"
    ...
    xmlns:prism="using:Prism.Windows.Mvvm"
    ...
    prism:ViewModelLocator.AutoWireViewModel="True">
...
</prism:SessionStateAwarePage>

このように、Views/[Name]PageとViewModels/[Name]PageViewModelを 対にして作成するだけで画面を増やすことができます。

サンプルコード

今回のサンプルコードは以下にあります。

https://github.com/nobukuma/PrismForUWPSample/tree/master/02-Unity/02-01-PrismUnityApp