Xamarin.Formsでコマンド（操作）をバインドするには？

# 概要
プロパティをバインディングする方法はわかったけど、処理をバインディングするにはどうすればいいの？ということで実際にやってみました。
[前の記事](http://qiita.com/Tachibana446/items/facc9c1b96b0c3dc7fd0)で作った、RGBのスライダーでラベルの色を変更するアプリに、白色にリセットするボタンを取り付けたいと思います。

プロパティをバインドするのと同じように、ViewModelのICommand型のプロパティをバインドします。

# ViewModel

~~~ C#
namespace XamarinSample2
{
    class RGBViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        double red, green, blue;
        Color color;

        public ICommand ResetColor { get; set; }

        public double Red
        {
            set
            {
                if (red != value)
                {
                    red = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Red"));
                    SetNewColor();
                }
            }
            get { return red; }
        }

        public double Green
        {
            set
            {
                if (green != value)
                {
                    green = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Green"));
                    SetNewColor();
                }
            }
            get { return green; }
        }
        public double Blue
        {
            set
            {
                if (blue != value)
                {
                    blue = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Blue"));
                    SetNewColor();
                }
            }
            get { return blue; }
        }

        public Color Color
        {
            set
            {
                if (color != value)
                {
                    color = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("Color"));
                    Red = value.R;
                    Green = value.G;
                    Blue = value.B;
                }
            }
            get { return color; }
        }

        public RGBViewModel()
        {
            this.Color = Color.White;
            ResetColor = new ResetColorCommand(this);
        }

        private void SetNewColor()
        {
            this.Color = Color.FromRgb(Red, Green, Blue);
        }
    }
}
~~~

ICommand型のプロパティResetColorを作り、それにICommandインターフェイスを実装した自作クラスResetColorCommandクラスのインスタンスをコンストラクタで割り当てています。
ResetColorCommandは以下の通りです。

~~~ C#
using System.Windows.Input;
using Xamarin.Forms;

namespace XamarinSample2
{
    class ResetColorCommand : ICommand
    {
        private RGBViewModel vm;

        public event EventHandler CanExecuteChanged;

        public ResetColorCommand(RGBViewModel viewmodel)
        {
            vm = viewmodel;
        }
        
        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            vm.Color = Color.White;
        }
    }
}

~~~

ExecuteメソッドでColorプロパティを白にするという処理を記述しています。

次はこのコマンドプロパティをViewにバインドしてみましょう

# View

~~~ XML
<?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:XamarinSample2;assembly=XamarinSample2"
             x:Class="XamarinSample2.View.StartPage">

  <StackLayout>
    <StackLayout.BindingContext>
      <local:RGBViewModel />
    </StackLayout.BindingContext>
    <Label x:Name="label"
           Text="TEXT TEXT"
           TextColor="{Binding Color}"
           FontSize="Large"
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand">
    </Label>
    <!-- RGB Slider -->
    <Slider Value="{Binding Red,Mode=TwoWay}" />
    <Slider Value="{Binding Green,Mode=TwoWay}" />
    <Slider Value="{Binding Blue,Mode=TwoWay}" />

    <!-- RGB Label -->
    <StackLayout Orientation="Horizontal">
      <Label Text="{Binding Red,StringFormat='{0:F2}'}"/>
      <Label Text="{Binding Green,StringFormat='{0:F2}'}" />
      <Label Text="{Binding Blue,StringFormat='{0:F2}'}" />
    </StackLayout>

    <Button Command="{Binding ResetColor}"  Text="Reset" />
  </StackLayout>
</ContentPage>
~~~

StackLayoutの一番下のボタンに注目してください。
Command属性に、他のプロパティと同じようにICommand型のプロパティをバインドしています。
実行すると、ボタンをクリックした時にカラーが白色になるはずです。

# まとめ
- ICommand型のプロパティをViewModelに作り、バインドする
- 実際のコマンドはICommandを実装したクラスで記述する

# おまけ
処理ごとにコマンドのクラスが増えると大変なので、渡されたラムダ式を実行するクラスを作ってみました。
WPFだとRelayCommandという似た機能を持つクラスがあるようなのですが、Xamarin.Formsではわからなかったので自作しました。

~~~ C#
namespace XamarinSample2
{
    class MyCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;

        Action _action;

        public MyCommand(Action action)
        {
            _action = action;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            _action();
        }
    }
}
~~~

使い方はこんな感じです。

~~~ C#
ResetColor = new MyCommand(() => { Color = Color.White; });
~~~

# 参考記事
[[XAML][C#][.NET][WPF]サンプルコードを見ながら理解するMVVMの基礎的な実装](http://d.hatena.ne.jp/kaorun/20141202/1417532472)