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

BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人的メモ

Xamarin.Forms の MVVM 基礎 ( Petzold's book - chapter.18 その4)

Xamarin.Forms での MVVM の基礎について、通称 Petzold's book の18章「MVVM」をざっくり試しています。
前回の続きです。

Overview

Petzold's bookの内容に沿ってにざっくり進めます。

  • 1. MVVM interrelationships(chapter.18 その1
    • MVVMの概要説明
  • 2. ViewModels and data binding(chapter.18 その1
    • 時計の表示をMVVMで行うサンプル
  • Interactive properties in a ViewModel(chapter.18 その2
    • スライダーの値を掛け算するサンプル
  • A Color ViewModel(chapter.18 その2
    • 色の変化を楽しむ?サンプル
  • Streamlining the ViewModel(chapter.18 その3
    • 「ViewModelの簡素化」についてまとめました(...本文を要約)
  • The Command interface 1(今回)
    • ICommandインターフェースの概要
    • 3の累乗計算アプリのサンプル
  • The Command interface 2(chapter.18 その5
    • 簡易足し算アプリのサンプル
  • ViewModels and the application lifecycle(次回以降)

Environment

検証した環境は以下で前回同様2016-09-29時点で最新の状態にしています。

ICommandインターフェースの概要

前回までは、プロパティのMVVMパターンを使ってデータバインディングの実装例をみてきましたが、次は、メソッドをバインドについてです。 そこで登場するのがICmmoandインターフェースです。

例えば、ButtonのClickイベントハンドラーをTapGestureRecognizerのTappedイベントハンドラーからそれぞれのメソッドを呼ぶのではなく、データバインディングによって直接メソッドを呼ぶ機能です。

これは、command interface(またはcommandig interface)と呼ばれるプロトコルで、8つのclassをサポートしています。

  • Button
  • MenuItem、ToolbarItem
  • SearchBar
  • TextCell、ImageCell
  • ListVeiw
  • TapGestureRecognizer

ICommandインターフェースは、3つの定義があります。内容を具体的に書くために、「ButtonをClickしたときの処理」を例として、3つの定義を説明します。

  • void Execure(object arg)メソッド
    Clickされたときのメイン処理。
  • bool CanExecute(object arg)メソッド
    Execureが実行できるかできないかを判断するメソッド。戻り値がfalseの場合は、Buttonは無効。
  • event EventHandler CanExecuteChangedイベントハンドラ
    CanExecuteメソッドを実行するイベントハンドラーってところでしょうか。

本文(518~519ページあたり)では、概念的な内容がたくさん書いてますので読んでみるとふむふむ♪となります。

3の累乗計算アプリ

3の累乗の計算結果を表示するアプリです。アプリの概要は、INCREASE(増加)ボタン、またはDECREASE(減)ボタンをクリックすることでで、指数が増減し、計算結果が更新されます。それぞれのボタンのクリックをICommandでデータバインドしています。 完成するアプリは以下の動作をするものです。

f:id:beachside:20161018153840g:plain

それでは、ViewModelから実装していきます。
まず、前回解説したViewModelの基底クラスとなるViewModelBaseクラスを、以下のように実装しています。

そして、今回利用するPowersViewModelクラス。

ボタンの動作にバインドさせるICommand型のIncreaseExponentCommandDecreaseExponentCommandを用意しています。

この二つはイミュータブルな仕様なので、readonlyプロパティとして定義しています。BaseValueプロパティも同様です。コンストラクターで値をセットしています。
18行目で、コンストラクターに引数が一つ必要としていますが、これは、後述のView側から渡します。

IncreaseExponentCommandが呼ばれたら、指数のプロパティ(Exponentプロパティ)の値を1追加、DecreaseExponentCommandが呼ばれたら、1減らす。指数の値に変更があれば、計算結果の値を更新するようにコーディングしています。

それでは、Viewの実装に移ります。Forms Xaml Pageを追加しましょう。PowersOfThreePage.xmalという名称で追加しました。

11行目で、バインドしているViewModelのコンストラクターに値を設定しています。この値を2にすれば...PowerOfTwoになります。 32行目と36行目で、ButtonのCommandにViewModelのCommandをバインドさせることで、Commandを発火させ指数や合計の値が変更され、データバインドによって画面の表示が更新されますね。
これで、最初のイメージの動作ができるようになりました。

動かしてみると、「Buttonちっさ!」と感じるので、Buttonの代わりにTapGestureRecognizerを使った実装に変更してみましょう。

ボタンのクリックや、タップの振る舞いがViewModelでCommandとして実装されているので、VeiwModel側のコードの変更なく適用できるのはいいですね。

f:id:beachside:20161018163059g:plain

次回のサンプルでは、CanExecuteCanExecuteChangedが登場してもう少し実用的なサンプルが出てきます。