Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Prism + ReactiveProperty入門

6,960 views

Published on

バトルプログラマーさんむけ資料

Published in: Technology

Prism + ReactiveProperty入門

  1. 1. Windows Phone開発のための Prism + ReactiveProperty基本 2015/6/26 まんつーまん@調布 大田 一希
  2. 2. Prismとは • Microsoft Patterns & Practicesチーム製のMVVMフレームワーク • 以下のプラットフォームをサポート • WPF(超複雑) • Silverlight(オワコン) • Windows store app • Windows Phone(今回の主題) • Xamarin(Preview) • 最近MS P&PチームからMVP主体のチームに移管された
  3. 3. Prism.StoreApps Prism.StoreAppsの中から電話向けに説明
  4. 4. Prism.StoreApps • Universal app(Windows store app + Windows Phone app)版Prism • 以下の構成要素がある • Prism.Mvvm :MVVMをサポートする基本クラスを提供 • Prism.Mvvm.Phone :↑にPhone固有機能を提供 • Prism.StoreApps :Win store app + WP app固有機能を提供 • Prism.StoreApps.Phone:↑にWP固有機能を提供
  5. 5. 覚えておきたいクラス
  6. 6. Prism.Mvvm • 本当にプレーンなMVVMの必要最低限の機能を提供するライブラリ • 以下の機能を提供 • BindableBase class :INotifyPropertyChangedの基本実装 • DelegateCommand class :ICommandの基本実装
  7. 7. Prism.Mvvm.Phone • 以下の機能を提供 • ViewModelLocator class :ViewとViewModelの紐づけ機能
  8. 8. Prism.StoreApps • PrismのUniversal app版 • 以下の機能を提供 • VisualStateAwarePage class :ページの基本クラス • ViewModel class :ViewModelの基本クラス • SessionStateService class :中断時の一時データ保存用クラス • FrameNavigationService class :画面遷移用クラス
  9. 9. Prism.StoreApps.Phone • Prism.StoreAppsのPhone特化版 • 以下の機能を提供 • MvvmAppBase class :Appクラスの基本クラス
  10. 10. クラス詳解 各クラスの使い方
  11. 11. BindableBase class • MVVMには必須のINotifyPropertyChangedの実装クラス • SetProperty<T>メソッドを使う こんな感じにsetが書ける コードスニペットに登録すると捗る
  12. 12. DelegateCommand class • ReactiveProperty使うならいらない子なので割愛
  13. 13. ViewModelLocator class • 命名規約(カスタマイズ可能だけどやりかたは割愛)によりViewと ViewModelを紐づける • 以下のような命名規約 • AppNamespace.Views.HogePage(View名) • AppNamespace.ViewModels.HogePageViewModel(View名+ViewModel) この2つを結びつける
  14. 14. ViewModelLocator class • ページの添付プロパティとして記述することで機能する
  15. 15. VisualStateAwarePage class • Pageに便利機能を追加 • Prismを使う上でページはこいつを継承する必要がある • 以下の機能を提供 • GoBackCommand property :戻る機能のCommand • GoHomeCommand property :トップページへ戻る機能のCommand • SaveState method :オーバーライドして中断時のデータ保存 • LoadState method :オーバーライドして中断時のデータ読込 • VisualStateの切り替え • DefaultLayout, PortraitLayout, MinimalLayoutを自動で切り替え(詳細は割愛)
  16. 16. VisualStateAwarePage class • 以下のように”空白のページ”テンプレートを書き換える • ViewModelLocatorも合わせて以下のようなXAMLがひな形 VisualStateAwarePageの名前 空間を定義 Pageタグを書き換え
  17. 17. VisualStateAwarePage class • 以下のように”空白のページ”のテンプレートを書き換える OnNavigatedToメソッドのオー バーライドを消す 基本クラスを VisualStateAwarePageにする
  18. 18. ViewModel class • BindableBaseを拡張して以下の機能を提供する • OnNavigatedToメソッド :画面遷移してきたときに呼ばれる • OnNavigatedFromメソッド :画面から離れるときに呼ばれる • 中断処理への対応 :RestorableState属性つけたプロパティの自動 復元
  19. 19. ViewModel class • 基本以下のような書き方になる
  20. 20. SessionStateService class • 中断時のデータ保存用クラス • 実際に使うときはISessionStateService interface • 後述するMvvmAppBaseのプロパティとして定義される • Dictionary<string, object> SessionState { get; }プロパティがある • ↑は、中断時のデータ保存場所 • RegisterKnownTypeメソッド • プリミティブ型以外をSessionStateに登録するときに型を登録するメソッド (しておかないと例外が飛ぶ)
  21. 21. FrameNavigationService class • 画面遷移をするためのクラス • 実際使うときはINavigationService interface • MvvmAppBaseクラスのプロパティとして定義される
  22. 22. FrameNavigationService class • 画面遷移の仕方 • ViewのXXXXPageに遷移するときは以下のように呼び出す • NavigationService.Navigate(“XXXX”, null); // 第二引数は画面遷移パラメータ • Frameにあるようなメソッドがある • GoBack() :戻る • CanBoBack() :戻れる場合true
  23. 23. MvvmAppBase class • Appクラスの基本クラス • なが~いApp.xaml.csをシンプルに書ける
  24. 24. MvvmAppBase class • Appクラスの定義方法 • App.xamlを以下のように書き換える MvvmAppBaseの名前空間を 定義 Appタグを書き換え
  25. 25. MvvmAppBase class • MainPageに遷移する場合のコードビハインド 長い処理を消して画面遷移す るだけの処理へ 基本クラスをMvvmAppBaseへ
  26. 26. 組み合わせて使う
  27. 27. Pageで画面遷移するには • MvvmAppBaseのOnInitializeAsyncメソッドをオーバーライドする • Pageに紐づくViewModelの生成をカスタマイズする • ViewModelにNavigationServiceを渡す • MainPageViewModelの生成をカスタマイズする場合は以下のような感じ
  28. 28. Pageで画面遷移するには • ViewModel側では以下のようにコンストラクタでINavigationServiceを受 け取り、それを使って画面遷移をする
  29. 29. Modelはどうするの? • Appクラスで作成してViewModelに渡すのがいいと思います
  30. 30. ReactiveProperty
  31. 31. ReactiveProperty • Reactive Extensions(Rx)をベースにしたMVVMサポートライブラリ • V ⇔ ViewModel ⇔ Modelの間をRxでシームレスに繋ぐのが特徴
  32. 32. ReactiveProperty • 以下のクラスを提供 • ReactiveProperty<T> class :ViewModelのプロパティ用 • ReactiveCommand class :ViewModelのCommand用 • ReadOnlyReactiveCollection<T> class:ViewModelのコレクション用 • その他拡張メソッドを提供 • INotifyPropertyChangedの拡張メソッド • ToReactivePropertyAsSynchronized method :MのプロパティとVMの ReactivePropertyの同期をとるためのメソッド • ObservableCollection<T>の拡張メソッド • ToReadOnlyReactiveCollection method :MのObservableCollection<T>と VMのReadOnlyReactiveCollection<T>の同期をとるためのメソッド
  33. 33. ReactiveProperty class • ViewModelに定義するプロパティ • public ReactiveProperty<string> Name { get; private set; }のように定義 • コンストラクタで初期化 • this.Name = new ReactiveProperty<string>(); // nullを持った状態 • this.Name = new ReactiveProperty<string>(“なまえ”); // 初期値を持った状態 • this.Name = source.ToReactiveProperty(); // IObservable<T>から変換 • this.Name = person.ToReactivePropertyAsSynchronized(x => x.Name); // Modelのプロ パティから変換
  34. 34. ReactiveProperty class • IObservable<T>からの変換 • 超便利なので覚えておくべき • model // 何かINotifyPropertyChangedの実装クラス .PropertyChangedAsObservable(x => x.Name) // IObservable<T>に変換 .ToReactiveProperty(); // ReactivePropertyに変換 • ↑でModelからViewModelへの一方通行値同期が可能
  35. 35. ReactiveProperty class • ToReactivePropertyAsSynchronized methodも便利 • model // INotifyPropertyChangedの実装クラス .ToReactivePropertyAsSynchronized(x => x.Name); //Nameプロパティと同期 • model // INotifyPropertyChangedの実装クラス .ToReactivePropertyAsSynchronized( x => x.Age, // Ageプロパティを x => x.ToString(), // M -> VMの時は文字列に変換して x => int.Parse(x)); // VM -> Mの時はintに変換する
  36. 36. ReactiveProperty class • ToReactivePropertyAsSynchronized methodも便利 • model // INotifyPropertyChangedの実装クラス .ToReactivePropertyAsSynchronized( x => x.Age, // Ageプロパティを x => x.Age.ToString(), // M -> VMの時は文字列に変換して x => int.Parse(x), // VM -> Mの時はintに変換する ignoreValidationErrorValue: true); // 変な値は通さない(次ページ参照)
  37. 37. ReactiveProperty class • 値の検証をサポート • // 何らかの方法でRPを作成 this.Hoge = xxxx.ToReactivePropertyAsSynchronized(…) // 検証ロジックを設定(nullの時はOKでそうじゃないときはエラーメッセージ) .SetValidateNotifyError(x => { var x = 0; if (int.TryParse(x, out x)) { return null; } else { return "整数を入力してください"; } });
  38. 38. ReactiveCommand class • IObservable<bool>から生成可能なCommand • public ReactiveCommand HogeCommand { get; private set; } • コンストラクタで以下のように初期化 • this.HogeCommand = new ReactiveCommand(); // 常に実行可能なコマンド • this.HogeCommand = source.ToReactiveCommand(); // IO<bool>がtrueの 時だけ実行可能なコマンド
  39. 39. ReactiveCommand class • コマンドの処理はSubscribeメソッドでやる • this.HogeCommand.Subscribe(_ => { // コマンド実行時の処理 });
  40. 40. ReadOnlyReactiveCollection class • ModelのObservableCollection<T>をViewModelで読み取り専用コレク ションとして公開する • 以下のように定義する • public ReadOnlyReactiveCollection<PersonViewModel> People { get; private set; } • 以下のように初期化する • // modelでObservableCollection<Person>が定義されてるとする this.People = model.People // model.Peopleと同期をとったPersonViewModelのコレクションを作成 .ToReadOnlyReactiveCollection(x => new PersonViewModel(x));
  41. 41. 組み合わせて使う PrismとReactiveProperty
  42. 42. 基本はModelは普通に書く • INotifyPropertyChangedとObservableCollection<T>による変更通知 • 機能をメソッドとして提供
  43. 43. ViewModelをPrism + ReactivePropertyで • ViewModel classを継承 • ReactiveProperty<T>でプロパティを定義 • OnNavigatedToメソッドでReactiveProperty<T>の初期化 • OnNavigatedFromメソッドで後始末
  44. 44. 後始末 • ReactivePropertyとModelを接続したら最後に接続を切ること • じゃないと予期せぬ処理が走ったりする • 具体的には • OnNavigatedToでCompositeDisposableに集める • OnNavigatedFromでDisposeする
  45. 45. 後始末 • こんな感じ • private CompositeDisposable disposable = new CompositeDisposable(); • OnNavigatedToで • this.Name = hoge.ToReactiveProperty().AddTo(this.disposable); • this.People = model.People .ToReadOnlyReactiveCollection(x => new PersonViewModel(x)) .AddTo(this.disposable); • OnNavigatedFromで • this.disposable.Dispose();
  46. 46. まとめ
  47. 47. Prism • BindableBase • ViewModelLocator • ViewModel • MvvmAppBase(NavigationService, SessionStateService) • OnInitializeAsync • OnLaunchApplicationAsync
  48. 48. ReactiveProperty • ReactiveProperty<T> • ReactiveCommand • ReadOnlyReactiveCollection<T> • INotifyPropertyChanged extension method • ToReactivePropertyAsSynchronized • ObservableCollection<T> extension method • ToReadOnlyReactiveCollection
  49. 49. まとめ • あとはケーススタディの積み重ね

×