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

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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

Xamarin Prism

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されてることが確認できます。