prism + reactiveproperty入門

49
Windows Phone開発のための Prism + ReactiveProperty基本 2015/6/26 まんつーまん@調布 大田 一希

Upload: -

Post on 04-Aug-2015

1.254 views

Category:

Technology


13 download

TRANSCRIPT

Page 1: Prism + ReactiveProperty入門

Windows Phone開発のためのPrism + ReactiveProperty基本

2015/6/26 まんつーまん@調布

大田 一希

Page 2: Prism + ReactiveProperty入門

Prismとは

• Microsoft Patterns & Practicesチーム製のMVVMフレームワーク• 以下のプラットフォームをサポート

• WPF(超複雑)

• Silverlight(オワコン)

• Windows store app

• Windows Phone(今回の主題)

• Xamarin(Preview)

•最近MS P&PチームからMVP主体のチームに移管された

Page 3: Prism + ReactiveProperty入門

Prism.StoreAppsPrism.StoreAppsの中から電話向けに説明

Page 4: Prism + ReactiveProperty入門

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固有機能を提供

Page 5: Prism + ReactiveProperty入門

覚えておきたいクラス

Page 6: Prism + ReactiveProperty入門

Prism.Mvvm

•本当にプレーンなMVVMの必要最低限の機能を提供するライブラリ

•以下の機能を提供• BindableBase class :INotifyPropertyChangedの基本実装

• DelegateCommand class :ICommandの基本実装

Page 7: Prism + ReactiveProperty入門

Prism.Mvvm.Phone

•以下の機能を提供• ViewModelLocator class :ViewとViewModelの紐づけ機能

Page 8: Prism + ReactiveProperty入門

Prism.StoreApps

• PrismのUniversal app版

•以下の機能を提供• VisualStateAwarePage class :ページの基本クラス

• ViewModel class :ViewModelの基本クラス

• SessionStateService class :中断時の一時データ保存用クラス

• FrameNavigationService class :画面遷移用クラス

Page 9: Prism + ReactiveProperty入門

Prism.StoreApps.Phone

• Prism.StoreAppsのPhone特化版

•以下の機能を提供• MvvmAppBase class :Appクラスの基本クラス

Page 10: Prism + ReactiveProperty入門

クラス詳解各クラスの使い方

Page 11: Prism + ReactiveProperty入門

BindableBase class

• MVVMには必須のINotifyPropertyChangedの実装クラス

• SetProperty<T>メソッドを使う

こんな感じにsetが書ける

コードスニペットに登録すると捗る

Page 12: Prism + ReactiveProperty入門

DelegateCommand class

• ReactiveProperty使うならいらない子なので割愛

Page 13: Prism + ReactiveProperty入門

ViewModelLocator class

•命名規約(カスタマイズ可能だけどやりかたは割愛)によりViewとViewModelを紐づける

•以下のような命名規約• AppNamespace.Views.HogePage(View名)

• AppNamespace.ViewModels.HogePageViewModel(View名+ViewModel)

この2つを結びつける

Page 14: Prism + ReactiveProperty入門

ViewModelLocator class

• ページの添付プロパティとして記述することで機能する

Page 15: Prism + ReactiveProperty入門

VisualStateAwarePage class

• Pageに便利機能を追加

• Prismを使う上でページはこいつを継承する必要がある

•以下の機能を提供• GoBackCommand property :戻る機能のCommand

• GoHomeCommand property :トップページへ戻る機能のCommand

• SaveState method :オーバーライドして中断時のデータ保存

• LoadState method :オーバーライドして中断時のデータ読込

• VisualStateの切り替え• DefaultLayout, PortraitLayout, MinimalLayoutを自動で切り替え(詳細は割愛)

Page 16: Prism + ReactiveProperty入門

VisualStateAwarePage class

•以下のように”空白のページ”テンプレートを書き換える• ViewModelLocatorも合わせて以下のようなXAMLがひな形

VisualStateAwarePageの名前

空間を定義

Pageタグを書き換え

Page 17: Prism + ReactiveProperty入門

VisualStateAwarePage class

•以下のように”空白のページ”のテンプレートを書き換える

OnNavigatedToメソッドのオー

バーライドを消す

基本クラスを

VisualStateAwarePageにする

Page 18: Prism + ReactiveProperty入門

ViewModel class

• BindableBaseを拡張して以下の機能を提供する• OnNavigatedToメソッド :画面遷移してきたときに呼ばれる

• OnNavigatedFromメソッド :画面から離れるときに呼ばれる

• 中断処理への対応 :RestorableState属性つけたプロパティの自動復元

Page 19: Prism + ReactiveProperty入門

ViewModel class

•基本以下のような書き方になる

Page 20: Prism + ReactiveProperty入門

SessionStateService class

•中断時のデータ保存用クラス

•実際に使うときはISessionStateService interface

•後述するMvvmAppBaseのプロパティとして定義される• Dictionary<string, object> SessionState { get; }プロパティがある

• ↑は、中断時のデータ保存場所

• RegisterKnownTypeメソッド• プリミティブ型以外をSessionStateに登録するときに型を登録するメソッド(しておかないと例外が飛ぶ)

Page 21: Prism + ReactiveProperty入門

FrameNavigationService class

•画面遷移をするためのクラス

•実際使うときはINavigationService interface

• MvvmAppBaseクラスのプロパティとして定義される

Page 22: Prism + ReactiveProperty入門

FrameNavigationService class

•画面遷移の仕方• ViewのXXXXPageに遷移するときは以下のように呼び出す

• NavigationService.Navigate(“XXXX”, null); // 第二引数は画面遷移パラメータ

• Frameにあるようなメソッドがある• GoBack() :戻る

• CanBoBack() :戻れる場合true

Page 23: Prism + ReactiveProperty入門

MvvmAppBase class

• Appクラスの基本クラス

• なが~いApp.xaml.csをシンプルに書ける

Page 24: Prism + ReactiveProperty入門

MvvmAppBase class

• Appクラスの定義方法

• App.xamlを以下のように書き換える

MvvmAppBaseの名前空間を

定義

Appタグを書き換え

Page 25: Prism + ReactiveProperty入門

MvvmAppBase class

• MainPageに遷移する場合のコードビハインド

長い処理を消して画面遷移す

るだけの処理へ

基本クラスをMvvmAppBaseへ

Page 26: Prism + ReactiveProperty入門

組み合わせて使う

Page 27: Prism + ReactiveProperty入門

Pageで画面遷移するには

• MvvmAppBaseのOnInitializeAsyncメソッドをオーバーライドする

• Pageに紐づくViewModelの生成をカスタマイズする• ViewModelにNavigationServiceを渡す

• MainPageViewModelの生成をカスタマイズする場合は以下のような感じ

Page 28: Prism + ReactiveProperty入門

Pageで画面遷移するには

• ViewModel側では以下のようにコンストラクタでINavigationServiceを受け取り、それを使って画面遷移をする

Page 29: Prism + ReactiveProperty入門

Modelはどうするの?

• Appクラスで作成してViewModelに渡すのがいいと思います

Page 30: Prism + ReactiveProperty入門

ReactiveProperty

Page 31: Prism + ReactiveProperty入門

ReactiveProperty

• Reactive Extensions(Rx)をベースにしたMVVMサポートライブラリ

• V ⇔ ViewModel⇔ Modelの間をRxでシームレスに繋ぐのが特徴

Page 32: Prism + ReactiveProperty入門

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>の同期をとるためのメソッド

Page 33: Prism + ReactiveProperty入門

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のプロパティから変換

Page 34: Prism + ReactiveProperty入門

ReactiveProperty class

• IObservable<T>からの変換• 超便利なので覚えておくべき

• model // 何かINotifyPropertyChangedの実装クラス.PropertyChangedAsObservable(x => x.Name) // IObservable<T>に変換.ToReactiveProperty(); // ReactivePropertyに変換

• ↑でModelからViewModelへの一方通行値同期が可能

Page 35: Prism + ReactiveProperty入門

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に変換する

Page 36: Prism + ReactiveProperty入門

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); // 変な値は通さない(次ページ参照)

Page 37: Prism + ReactiveProperty入門

ReactiveProperty class

•値の検証をサポート• // 何らかの方法でRPを作成

this.Hoge = xxxx.ToReactivePropertyAsSynchronized(…)// 検証ロジックを設定(nullの時はOKでそうじゃないときはエラーメッセージ).SetValidateNotifyError(x =>{

var x = 0;if (int.TryParse(x, out x)) { return null; }else { return "整数を入力してください"; }

});

Page 38: Prism + ReactiveProperty入門

ReactiveCommand class

• IObservable<bool>から生成可能なCommand• public ReactiveCommand HogeCommand { get; private set; }

• コンストラクタで以下のように初期化• this.HogeCommand = new ReactiveCommand(); // 常に実行可能なコマンド

• this.HogeCommand = source.ToReactiveCommand(); // IO<bool>がtrueの時だけ実行可能なコマンド

Page 39: Prism + ReactiveProperty入門

ReactiveCommand class

• コマンドの処理はSubscribeメソッドでやる• this.HogeCommand.Subscribe(_ =>

{// コマンド実行時の処理

});

Page 40: Prism + ReactiveProperty入門

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));

Page 41: Prism + ReactiveProperty入門

組み合わせて使うPrismとReactiveProperty

Page 42: Prism + ReactiveProperty入門

基本はModelは普通に書く

• INotifyPropertyChangedとObservableCollection<T>による変更通知

•機能をメソッドとして提供

Page 43: Prism + ReactiveProperty入門

ViewModelをPrism + ReactivePropertyで

• ViewModel classを継承

• ReactiveProperty<T>でプロパティを定義

• OnNavigatedToメソッドでReactiveProperty<T>の初期化

• OnNavigatedFromメソッドで後始末

Page 44: Prism + ReactiveProperty入門

後始末

• ReactivePropertyとModelを接続したら最後に接続を切ること

• じゃないと予期せぬ処理が走ったりする

•具体的には• OnNavigatedToでCompositeDisposableに集める

• OnNavigatedFromでDisposeする

Page 45: Prism + ReactiveProperty入門

後始末

• こんな感じ• 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();

Page 46: Prism + ReactiveProperty入門

まとめ

Page 47: Prism + ReactiveProperty入門

Prism

• BindableBase

• ViewModelLocator

• ViewModel

• MvvmAppBase(NavigationService, SessionStateService)• OnInitializeAsync

• OnLaunchApplicationAsync

Page 48: Prism + ReactiveProperty入門

ReactiveProperty

• ReactiveProperty<T>

• ReactiveCommand

• ReadOnlyReactiveCollection<T>

• INotifyPropertyChanged extension method• ToReactivePropertyAsSynchronized

• ObservableCollection<T> extension method• ToReadOnlyReactiveCollection

Page 49: Prism + ReactiveProperty入門

まとめ

• あとはケーススタディの積み重ね