kazuakix の日記

Windows Phone とか好きです

標準の RelayCommand をつかってみる

少し前から View にイベントハンドラを書かずに ViewModel のコマンドを指定するように心がけています。


主に Prism の DelegateCommand のお世話になっているのですが、つい先日 基本ページを作成したときに自動的に追加されれるクラスの中に RelayCommand という実装が含まれている事に気が付きました。

RelayCommand を使ってみる

例えば先日の MapControl の位置を更新するコードを例にしてみます。

public class MainPageViewModel 
{
    public void StartGeolocator()
    {
        if (_geoLocator == null) _geoLocator = new Geolocator();

        _geoLocator.PositionChanged += OnGeoLocatorPositionChanged;
    }

    private async void OnGeoLocatorPositionChanged(Geolocator sender, PositionChangedEventArgs args)
    {
        await _coreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            Location =
                new Geopoint(new BasicGeoposition
                {
                    Longitude = args.Position.Coordinate.Point.Position.Longitude,
                    Latitude = args.Position.Coordinate.Point.Position.Latitude
                });
        });
    }
}

コマンドを使わない場合

これをアプリケーション バーから呼ぼうとしたらこんな感じにしていました。

XAML でイベントを追加して、

<Page.BottomAppBar>
    <CommandBar>
        <AppBarButton Icon="Play" Label="start" 
            Click="AppBarButton_Click"/>
    </CommandBar>
</Page.BottomAppBar>

コードビハインドで中身(ViewModel のメソッド呼び出し) を書きます。

private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
    ViewModel.StartGeolocator();
}

RelayCommand を使う場合

ViewModel に RelayCommand 型のプロパティを作って、呼び出したいメソッドを渡しておきます。

public class MainPageViewModel : BindableBase
{
    public RelayCommand StartGeolocatorCommand { get; set; }

    public MainPageViewModel()
    {
        StartGeolocatorCommand = new RelayCommand(StartGeolocator);
    }
}

後は XAML でボタンの Command プロパティに指定するだけで OK 。コードビハインドを書く必要はありません。

<Page.BottomAppBar>
    <CommandBar>
        <AppBarButton Icon="Play" Label="start" 
            Command="{Binding StartGeolocatorCommand}"/>
    </CommandBar>
</Page.BottomAppBar>

 
これだけの例だと若干微妙な気もしますが、ユニバーサルアプリなどではできるだけコードの共有ができた方がいいのでコードビハインドを少なくしておくというのは有効な手段だと思います。*1

何よりもせっかく標準で追加してくれるのですから有効活用しないともったいないですよね。

*1:俺は View まで共有するぜ!というすごい方もいらっしゃるようですが...