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

かずきのBlog@hatena

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

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