かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Xamarin.Forms + Prism.FormsでVとVMを結びつける

Prism.Formsを使えば簡単にMVVMのViewのBindingContextにViewModelを設定できます。Hello worldでもやったっちゃやりましたが、もう一度改めてやってみようと思います。

VとVMを紐づけるには、ViewModelLocatorというクラスを使用します。ViewModelLocatorクラスのAutowireViewModel添付プロパティをTrueにすることでViewとViewModelを命名規約に従って紐づけることができます。この添付プロパティは、Pageに対して設定を行います。

命名規約

ViewとViewModelの紐づけの命名規約はデフォルトでは以下のようになっています。

Viewの名前

Viewの名前は、Views名前空間に任意の名前で作成します。

ViewModelの名前

ViewModelはViewModels名前空間にViewのクラス名 + ViewModelという名前で作成します。 例えばViews/MainPageというViewに対しては、ViewModels/MainPageViewModelという名前で作ります。例外として、Viewの名前がXXXViewのようにViewで終わる場合は、XXXViewModelというようにModelが名前の最後につく形になります。

やってみる

Prism Unity App (Forms)のプロジェクトを作成します。すると出来上がってます!ということで見て行ってみましょう。

Prism Unity App (Forms)のプロジェクトを新規作成すると以下のような形になっています。

f:id:okazuki:20160417143255p:plain

先ほど説明した命名規約に従ってViewとViewModelが作成されていることがわかります。

MainPage.xamlを見ると、最初に説明したViewModelLocator.AutowireViewModel="True"という記述があるということがわかります。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="PrismUnityApp7.Views.MainPage"
             Title="MainPage">
  <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
    <Label Text="{Binding Title}" />
  </StackLayout>
</ContentPage>

見るだけではなんなので、自分でもやってみようと思います。Viewをまず作ります。NextPageという名前でPrism Content Pageを作成します。(Prism Template Packをインストールしていると出てきます。)

そうすると、ViewModelLocatorが設定された画面が作成されます。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="PrismUnityApp7.Views.NextPage">

</ContentPage>

ViewModels名前空間にNextPageViewModelという名前でPrism ViewModelを作成します。新規作成時点で以下のようなコードが生成されます。

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PrismUnityApp7.ViewModels
{
    public class NextPageViewModel : BindableBase
    {
        public NextPageViewModel()
        {

        }
    }
}

ViewとViewModelが紐づけされていることが確認できるように、ViewModelにプロパティを追加して、Viewで表示してみようと思います。 ViewModelにTextプロパティを追加します。

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PrismUnityApp7.ViewModels
{
    public class NextPageViewModel : BindableBase
    {
        public string Text => "Hello MVVM world!!";
        public NextPageViewModel()
        {

        }
    }
}

ViewにLabelを追加します。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="PrismUnityApp7.Views.NextPage">
  <Label Text="{Binding Text}" />
</ContentPage>

ViewをUnityのコンテナに登録

AppクラスのRegisterTypesメソッドでNextPageを登録します。

protected override void RegisterTypes()
{
    this.Container.RegisterTypeForNavigation<MainPage>();
    this.Container.RegisterTypeForNavigation<NextPage>();
}

OnInitializedで現在MainPageに遷移している処理をMainPageに遷移するのからNextPageに変更します。

protected override async void OnInitialized()
{
    InitializeComponent();

    await this.NavigationService.Navigate("NextPage");
}

実行して動作確認

実行すると以下のようになります。

f:id:okazuki:20160417145154p:plain

ViewとViewModelが紐づけされて、ちゃんとBindingされてることが確認できます。