銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

MvvmCross で Windows Phone アプリケーションを作る ~その3 コマンドと画面遷移 ~

書くといって時間がだいぶ経ちましたが、MvvmCross シリーズの第3回目です。

MvvmCross で Windows Phone アプリケーションを作る ~その1~

MvvmCross で Windows Phone アプリケーションを作る ~その2 ValueConverters ~

今回はコマンドの定義と画面遷移についてです。MVVMでViewのEventに応じて、ViewModelのなんらかのロジックを実行する場合、ViewModel側で ICommand 型のプロパティを定義して、それをViewのCommandにBindさせることで実行することができます。今回、LongListSelector の要素をTapするとその項目の詳細ページに画面遷移するコマンドを作成することにします。

f:id:tanaka733:20140119224723p:plain

f:id:tanaka733:20140119224725p:plain

コマンドの定義とBinding

LongListSelector の定義はこんな感じになります。

View側の注意点としては、LongListSelectorのTapイベントに直接CommandをBindinsさせることができないため、 Interaction.Triggers -> EventTrigger -> InvokeCommandAction という順で指定したEventでTriggerを発生させて、Bindingさせたコマンドを実行させるようにしています。

このとき、Windows Phoneプロジェクトの参照の追加で、Microsoft.Expression.Interactions と System.Windows.Interactivity を追加する必要があります。

f:id:tanaka733:20140119225440p:plain

つぎにViewModelです。まず、LongListSelectorなので、DataContextにBindingしている MainViewModel には、ObservableCollection 型の Roomsプロパティを定義しています。そして、RoomSummaryViewModel に MoveCommand を定義しています。

MVVM Light では RelayCommand というICommand インターフェースを実装したクラスがあって、コマンドで処理したいメソッドをAction型で渡せるようになっていますが、同様の仕組みがMvvmCross にも MvxCommand というクラスで存在しています。使い方も同様で、上のコードように実行したいメソッド(ExecuteMoveCommand)をAction型で渡しています。 実行している処理は画面遷移なのですがその説明のまえに MvcCommand を定義するときはVMのプロパティ同様コードスニペットがあると捗ります。

画面遷移

上にあるように、画面遷移は ViewModelを作成するときに継承する MvxViewModel が継承している MvxNavigatingObject に定義されている ShowViewModel メソッドを使います。いくつかオーバーロードが用意されているが、ViewModelのクラスと遷移先に渡すパラメーターを指定するのが基本になります。

さて、 Mvvm Light で Windows Phoneの画面遷移をする - 銀の光と碧い空 で説明したように、Windows Phone SDKではページを指定して画面遷移を行う。ところがMvvmCross ではViewModelを指定します。ここが大きく違う点になります。

なぜこんなことになっているかというのは、MvvmCross がViewModel をPCLとして作り、View側を各プラットフォームごとに書く構造にしているためだと思われます。この構造だと、ViewModelはView側に依存できないため、ViewModelを指定して画面遷移するしかありません。その代わり、ViewModelに対応するViewを決める必要があります。これはデフォルトでは、XxxViewModel というViewModelに対して、Views/XxxView.xaml というViewが対応します(Viewsフォルダ以下に配置する必要あり)。

f:id:tanaka733:20140120002628p:plain

さて、上のサンプルでは匿名オブジェクトを使ってパラメーターを渡していますが、それを受け取るのもViewModel側で行います。遷移先のViewModelにInitというメソッドを作って引数で受けます。

ただし使える型は、以下の通りです。

  • int
  • long
  • double
  • string
  • Guid
  • それらの列挙

もともとWindowsPhone ではURLのクエリ文字列として渡すので、特に問題ないと思います。 また、上の使える型だけをパブリックなプロパティとし、引数なしのコンストラクタを持った単純なクラスも渡すことができます。

ViewModel to ViewModel navigation · MvvmCross/MvvmCross Wiki · GitHub

今回はコマンドと基本的な画面遷移の説明でした。