かずきのBlog@hatena

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

Xamarin.FormsでMVVM Light ToolkitとReactivePropertyを使ってみた

Prism.Mvvmのほうが好みなんですが、こいつがSilverlight for Windows Phone 8をサポートしないので、SL for WP8もサポートしてる(すごいよね…)MVVM Light Toolkitを試してみました。

ViewModelLocatorの作成

SimpleIoCというDIコンテナがついてるけど、個人的にUnity推しなので、Unity使うようにしてViewModelLocatorを作りました。こんな感じで。

using App13.ViewModels;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;

namespace App13
{
    public static class ViewModelLocator
    {
        static ViewModelLocator()
        {
            var c = new UnityContainer();
            ServiceLocator.SetLocatorProvider(new ServiceLocatorProvider(() => new UnityServiceLocator(c)));
        }

        public static MainViewModel Main
        {
            get { return ServiceLocator.Current.GetInstance<MainViewModel>(); }
        }
    }
}

ViewModelの作成

コマンド押したらダイアログが出るイメージです。

using Codeplex.Reactive;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using System;

namespace App13.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        public ReactiveProperty<string> Label { get; private set; }

        public ReactiveCommand AlertCommand { get; private set; }

        public MainViewModel()
        {
            this.Label = new ReactiveProperty<string>("Hello world");

            this.AlertCommand = new ReactiveCommand();
            this.AlertCommand.Subscribe(_ => this.MessengerInstance.Send(new NotificationMessage("こんにちは!")));
        }
    }
}

ダイアログ表示用ビヘイビアの作成

これでいいのか自信がないけどつくってみました。

using GalaSoft.MvvmLight.Messaging;
using Xamarin.Forms;

namespace App13.Services
{
    public class DialogBehavior : Behavior<Page>
    {
        private Page page;
        protected override void OnAttachedTo(Page bindable)
        {
            base.OnAttachedTo(bindable);
            this.page = bindable;
            Messenger.Default.Register<NotificationMessage>(this, this.Alert);
        }

        public void Alert(NotificationMessage message)
        {
            this.page.DisplayAlert("メッセージ", message.Notification, "OK");
        }

        protected override void OnDetachingFrom(Page bindable)
        {
            base.OnDetachingFrom(bindable);
            Messenger.Default.Unregister<NotificationMessage>(this);
        }
    }
}

Viewの作成

XAMLでさくっとね。

<?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:local="clr-namespace:App13;assembly=App13"
  xmlns:services="clr-namespace:App13.Services;assembly=App13"
  x:Class="App13.Views.MainPage"
  BindingContext="{x:Static local:ViewModelLocator.Main}">
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness"
                iOS="0, 20, 0, 0" />
  </ContentPage.Padding>
  <ContentPage.Behaviors>
    <services:DialogBehavior />
  </ContentPage.Behaviors>
  <StackLayout>
    <Label Text="{Binding Label.Value}" />
    <Button Text="こんにちは" Command="{Binding AlertCommand}" />
  </StackLayout>
</ContentPage>

App.csの書き換え

App.csのMainPageの設定を上で作ったページに書き換えます。これは忘れがち。

using App13.Views;
using Xamarin.Forms;

namespace App13
{
    public class App : Application
    {
        public App()
        {
            // The root page of your application
            MainPage = new MainPage();
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

実行して動作確認

実行してボタンを押すとダイアログが出た!

f:id:okazuki:20150211233002p:plain

ソースコード

runceel/Xamarin.Forms-MVVMLight-RxProp-HelloWorld · GitHub