Prism.Mvvmは非常にシンプルなMVVMをサポートするライブラリです。Xamarin.Formsでも使わない手はない!ということで使ってみました。
環境設定
Windows Phoneのプロジェクトを消します。日本で出てないし、Prism.Mvvmサポートしてないプラットフォームなので泣く泣く…。この時点で私はAndroidしか試せないのでiOSも消してしまいました。
PCLのプロパティを開いてWindows Phoneのチェックを外しておきます。
NuGetでの導入
Prism.Mvvmで検索してPCLとAndroidのプロジェクト両方にPrism.Mvvmを追加します。
Viewの作成
Viewsという名前のフォルダを作ってForms Xaml Pageを作成します。
Prism.MvvmのVとVMの紐づけ機能を使うには、ViewがIViewインターフェースを実装してないといけないので、これを実装します。DataContextというプロパティが必要になるのでBindingContextをラップする形で実装します。ついでに、コンストラクタにViewModelLocationProviderのAutoWireViewModelChangedを呼び出しておいて、紐づけ機能を有効にしておきます。
using Microsoft.Practices.Prism.Mvvm; using Xamarin.Forms; namespace App8.Views { publicpartialclass MainPage : ContentPage, IView { public MainPage() { InitializeComponent(); ViewModelLocationProvider.AutoWireViewModelChanged(this); } publicobject DataContext { get { returnthis.BindingContext; } set { this.BindingContext = value; } } } }
ViewModelの作成
ViewModelsフォルダを作って、そこにViewのクラス名+ViewModelという命名規約でViewModelを作成します。この例ではMainPageViewModelですね。とりあえず、適当に。
using Microsoft.Practices.Prism.Mvvm; using System.Windows.Input; using Xamarin.Forms; namespace App8.ViewModels { publicclass MainPageViewModel : BindableBase { privatestring mainText; publicstring MainText { get { returnthis.mainText; } set { this.SetProperty(refthis.mainText, value); } } public ICommand HelloCommand { get; private set; } public MainPageViewModel() { this.MainText = "Hello world"; this.HelloCommand = new Command(() => this.MainText = "こんにちは世界"); } } }
XAMLの作成
さて、Viewに戻ってViewModelに紐づくXAMLを書いていきます。といっても、デフォルトでMainTextにバインドされてるLabelが用意されてるので、ここではStackLayoutとButtonを追加しただけです。Xamarin Studioだと若干のインテリセンスが効くので精神衛生にいいですが、Visual Studioで書くと発狂しそうになります。ここらへん、そのうち出てくるであろうデザイナに期待したいところですね。
<?xml version="1.0" encoding="utf-8"?><ContentPage xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"x:Class="App8.Views.MainPage"><StackLayout><Label Text="{Binding MainText}"VerticalOptions="Center"HorizontalOptions="Center" /><Button Text="Hello"Command="{Binding HelloCommand}" /></StackLayout></ContentPage>
MainPageの設定
App.csのMainPageを、先ほど作成したMainPageクラスに差し替えます。
public App() { // The root page of your application MainPage = new MainPage(); }
実行
実行すると以下のようになります。
Unity(DIコンテナのほう)との連携
Prism.MvvmのVとVMの連携は、UnityによるDIと連携するとうれしいと個人的に思ってます。UnityをプロジェクトにNuGetから追加します。
ついでに、Prism.PubSubEventsも追加しておきます。Prism.PubSubEventsのクラスをVMにDIしてみたいと思います。
App.csのコンストラクタでUnityの初期化とViewModelのインスタンス化の処理の書き換えを行います。
public App() { var c = new UnityContainer(); // EventAggregatorをシングルトンで管理してもらう c.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager()); // ViewModelをUnityから取得するようにする ViewModelLocationProvider.SetDefaultViewModelFactory(t => c.Resolve(t)); MainPage = new MainPage(); }
ViewModelのコンストラクタなどでIEventAggregatorを受け取るようにするとUnityが勝手にインスタンスを設定してくれます。
public MainPageViewModel(IEventAggregator eventAggregator)
Modelのルート要素をDIしてもらったり、設定情報を保持するクラスをDIしてもらったりとか色々便利です。オブジェクトのインスタンスの管理をお任せできるので個人的に気に入ってます。
まとめ
Prism.Mvvm + UnityはXamarin.Formsでも使える(ただしWindows Phoneは除く)