はじめに
Prism入門3回目です。今回はDelegateCommandについて説明します。
MVVMではViewは描画しかできません。メソッドはVMに記述される必要があります。
Viewにメソッドは基本的に書かないので、バインドでメソッドを実行できるようにする必要があります。
そこで登場するのが、ICommandインターフェースです。
例えば、ICommandインターフェースを持ったクラスのプロパティをボタンでバインドするとボタンを押した時にコマンドが実行されます。
ただ、メソッドごとにICommandインターフェースを持ったクラスを用意するのはとても面倒です。そこでDelegateCommandを使用します。
DelegateCommand
DelegateCommandは初期化時にラムダ式やメソッドを引数に指定できます。
引数には実行する内容と、実行できるか、の2つのメソッドを指定できます。
cs
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
namespace prismSample.ViewModels
{
public class MainPageViewModel : BindableBase, INavigationAware
{
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public DelegateCommand Clicked { get; private set; }
public MainPageViewModel(INavigationService navigationService)
{
Clicked = new DelegateCommand(
() => { Title = "Clicked;"; }, // 実行される内容
() => true); // 実行できるか?
}
}
}
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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" prism:ViewModelLocator.AutowireViewModel="True" x:Class="prismSample.Views.MainPage" Title="MainPage">
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="{Binding Title}" />
<Button Command="{Binding Clicked}" Text="Click!" />
</StackLayout>
</ContentPage>
当然、アプリケーションの実行中にボタンを押せるかどうかが変化することがあります。
例えば、全ての入力欄に内容が入力された時や、他の処理が終わった後などです。
その時に実行できるか、のフラグが変化したかを通知する必要があります。
ICommand.CanExecuteChanged
を実行すればいいですが、
色んなところに実装が書かれることになり、とても面倒です。
そこで、DelegateCommandには、フラグが変更したかを楽に通知する方法があります。
それはObservesPropertyです。
今回はアプリケーションが処理を行なっている時はボタンを押せないような実装を想定しました。IsBusyプロパティとObservesPropertyが追加されています。
DelegateCommandの生成に続けてObservesPropertyを実行すると引数に指定されているプロパティが変更するたびに実行できるかの可否の通知が行われるようになります。
private bool _isBusy = false;
public bool IsBusy
{
get { return _isBusy; }
set { SetProperty(ref _isBusy, value); }
}
public DelegateCommand Clicked { get; private set; }
public MainPageViewModel(INavigationService navigationService)
{
Clicked = new DelegateCommand(
() => { Title = "Clicked;"; },
() => !IsBusy).ObservesProperty(() => IsBusy);
}
こうすると全てのコマンドに関する実装が一箇所にまとまり、挙動がわかりやすくなります。
最後に
他にもPrismにはコマンドを補助する機能があります。
興味がありましたら、調べてみてください。