Xamarin.Forms は、Xamarin に新たに搭載されたクロスプラットフォームUIフレームワーク&MVVMフレームワークです。

 ReactiveProperty は、MVVMの(特に ViewModelの)実装を強力にサポートしてくれる、Reactive Extensions を基盤としたライブラリです。

両者を組み合わせると、Android/iOSアプリが COOL な感じで書けるんじゃないか、という事で試してみました。

0. 環境など

Mac + Xamarin Studio を使いますが、Windows + Visual Studio + Xamarin-Addin でもイケると思います。

1. 導入

プロジェクトの作成

新規ソリューションを、[C#]−[Mobile Apps]−[Blank App(Xamarin.Forms Portable)]で作成します。

PCL の Profile を変更

 作成されたソリューションの一番上にあるプロジェクト(.Android とか .iOS が付いていないやつ)のプロジェクト設定を開いて Profile を PCL 4.5 - Profile49 に変更します。元々の Profile78 では ReactiveProperty が Nuget からインストールできないためです。最近のプラットフォームを対象にするなら、あまり影響はなさそうです。

Nuget で Reactive Extensions と ReactiveProperty を追加

 メニューの[プロジェクト]ー[Add Packages]で Nuget のダイアログを開き、図のように 「Reactive Extensions - Main Library」と「ReactiveProperty Portable」を追加します。

(Reactive Extensions の追加の際、なにやらWarningが出るようですが、とりあえず進めます。)

2. ViewModel の実装

 PCL のプロジェクトに、FirstViewModel.cs を作成します。
 FirstViewModel は、以下のようなプロパティとコマンドを持ちます。

  • InputTextプロパティ : EditBox の入力に応じて更新
  • DisplayTextプロパティ : InputText の変化から1秒後に、InputText を大文字にして更新
  • Clearコマンド : InputText が ‘clear’ の時のみ有効。実行すると InputText を空にする。

これらの実装が下のようになります。

```csharp FirstViewModel.cs
using System;
using Codeplex.Reactive;
using System.Reactive.Linq;

namespace FormsWithRxProperty.ViewModels
{
public class FirstViewModel
{
private readonly ReactiveProperty _inputText = new ReactiveProperty("Hoge"); public ReactiveProperty InputText { get { return _inputText; } }

    public ReactiveProperty<string> DisplayText
    {
        get; private set;
    }

    public ReactiveCommand Clear
    {
        get; private set;
    }

    public FirstViewModel()
    {
        // DisplayText は、InputText の変更から1秒後に大文字にして更新
        this.DisplayText = _inputText
            .Delay(TimeSpan.FromSeconds(1))
            .Select(x => x.ToUpper())
            .ToReactiveProperty();

        // InputText が `clear` の時に実装可能
        this.Clear = _inputText
            .Select(x => x.Equals("clear"))
            .ToReactiveCommand();
        // 実行されたら、InputText を空にする
        this.Clear.Subscribe(_ => _inputText.Value = String.Empty);
    }
    
} } ```

 面倒な INotifyPropertyChanged の実装が必要なく、すっきりと記述できます。
 また、他のプロパティに関連して(反応して)値が変化するプロパティや、コマンドの利用可否などが、Reactive Extensions の機能により、流れるように記述できます。

3. 画面及び ViewModel との Binding の実装

 画面(UI)は、Xamarin.Forms の恩恵で、Android/iOS 共通で実装できます。XAML も使えますが、よく知らないのでコードでUIを記述します。

 PCL のプロジェクトに、 FirstPage.cs を作成し、以下のように実装します。

```csharp FirstPage.cs
using System;
using Xamarin.Forms;
using FormsWithRxProperty.ViewModels;

namespace FormsWithRxProperty.Pages
{
public class FirstPage : ContentPage
{
public FirstPage()
{
// UI
var entry = new Entry
{
Text = “Hello, Forms!”,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.FillAndExpand,
};

        var label = new Label
        {
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.CenterAndExpand,
        };

        var button = new Button
        {
            Text = "Clear (type 'clear' to enable)",
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.FillAndExpand,
        };

        this.Content = new StackLayout
        {
            Padding = new Thickness(50f),
            VerticalOptions = LayoutOptions.Start,
            HorizontalOptions = LayoutOptions.Fill,
            Orientation = StackOrientation.Vertical,
            Children =
            {
                entry,
                label,
                button
            }
        };

        // ViewModel との Binding
        this.BindingContext = new FirstViewModel();
        entry.SetBinding<FirstViewModel>(Entry.TextProperty, vm=>vm.InputText.Value);
        label.SetBinding<FirstViewModel>(Label.TextProperty, vm=>vm.DisplayText.Value);
        button.SetBinding<FirstViewModel>(Button.CommandProperty, vm=>vm.Clear);
    }
} } ```

 ちょっと長いですが、画面に「エディットボックス」「ラベル」「ボタン」が縦に並んでいるだけです。

 下部の4行で、FirstViewModel の各プロパティ、コマンドと Bind しています。

 もともとあった App.cs は、FirstPage を生成するだけにします。

```csharp App.cs
using System;
using Xamarin.Forms;
using FormsWithRxProperty.Pages;

namespace FormsWithRxProperty
{
public class App
{
public static Page GetMainPage()
{
return new FirstPage();
}
}
}



## 動かす!

 .Android か .iOS の付いたプロジェクトをスタートアップにして、実行します。

![](/assets/images/posts/using_xamarin_forms_with_reactiveproperty_03.gif)

### 追記 2014.9.10

実機で動作確認するの忘れてました(実機はAOTなのに対してiOSシミュレータはJITなのでリフレクションとかが普通に動いてしまう)。
実機でも問題なく動作しました!

## 追記 2014.9.11 INotifyPropertyChanged の利用

ViewModel は ``INotifyPropertyChanged`` を実装して作成するのが一般的です。既にそのようにして作られた ViewModel でも ``IObservable`` 化して、ReactiveProperty で利用できます。

```csharp SecondViewModel.cs
public class SecondViewModel : INotifyPropertyChanged
{
    public ReactiveProperty<string> ValidationAttr { get; private set; }
    public event PropertyChangedEventHandler PropertyChanged;

    private string _myName = "HoGe";
    public string MyName 
    {
        get { return _myName; }
        set 
        { 
            if (_myName == value) return;

            _myName = value;
            PropertyChanged(this, new PropertyChangedEventArgs("MyName"));
        }
    }

    public ReactiveProperty<string> LowerText { get; private set; }

    private ICommand _resetCommand;
    public ICommand ResetCommand
    {
        get
        {
            return _resetCommand ?? (_resetCommand = 
                new Xamarin.Forms.Command(() => MyName = "XAAAAMAAARIN!!"));
        }
    }

    public SecondViewModel()
    {
        this.LowerText = this.ObserveProperty(x => x.MyName)
            .Select(x => x.ToLower())
            .ToReactiveProperty();
    }
}

まとめ

 Reactive Extensions のメリットを活かして MVVM を構築できる ReactiveProperty と、ワンソースで Android/iOS の画面を定義でき、さらに Binding までも共通にできる Xamarin.Forms の組み合わせは、今後のモバイルアプリケーション開発をとても効率的にしてくれます、 そしてなにより楽しい!

 今回のサンプルプログラムは

 に置きましたので、是非試してみてください。

ReactiveProperty

Xamarin.Forms

Xamarin
Android
iOS
Reactiveextensions
ReactiveProperty

published

Ads

Read more!

amay077

Microsoft MVP(Xamarin). フルリモートワーカー. Geospatial Mobile app developer. Love C#.

amay077 amay077