NuGet Gallery | ReactiveProperty 2.0.0-pre3
今回は以下の変更を含んでます。
CountNotifyerのINotifyPropertyChangedの実装
CountNotifyerクラスがINotifyPropertyChangedインターフェースを実装してCountプロパティの変更通知を受け取れるようにしました。
EventToReactiveCommandの追加
イベントをReactiveCommandに接続するときに、間にRxのレイヤを1枚噛ますことができるEventToReactiveCommandクラスを追加しました。EventTrigger等と一緒に使います。要はコマンドを呼び出す前に任意の処理を挟んで、なおかつ処理の結果をコマンドに渡すことが出来るようになります。
Commandが呼び出される前の処理はReactiveConverter<T, U>かDelegateConverter<T, U>のどちらかを継承して作成します。ReactiveConverterのほうが、IObservable<T>を受け取ってIObservable<U>を返す処理を記述して、DelegateConverterのほうがTを受け取ってUを返す処理を記述します。
ReactivePropertyのサンプルプログラムに入っている例では、ファイルダイアログを出して選択したファイルをCommandに渡すようにしています。コードを以下に示します。
// Converterpublicclass OpenFileDialogConverter : ReactiveConverter<EventArgs, string> { protectedoverride IObservable<string> Convert(IObservable<EventArgs> source) { return source .Select(_ => new OpenFileDialog()) .Do(x => x.Filter = "*.*|*.*") .Where(x => x.ShowDialog() == true) // Show dialog .Select(x => x.FileName); // convert to string } }
EventArgsを受け取ったらダイアログを表示して、OKが押された場合のみ選択されたファイルのパスを流しています。
このConverterをCommandと接続するためにEventToReactiveCommandを使用します。EventToReactiveCommandのCommandプロパティに接続先のCommandをバインドして、先ほど作成したConverterをConverterプロパティ(コンテンツプロパティなので中に直接書けます)にセットします。
<Button Content="Select file"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <!-- set the command, called after the converter --> <Interactivity:EventToReactiveCommand Command="{Binding SelectFileCommand, Mode=OneWay}"> <Views:OpenFileDialogConverter/> </Interactivity:EventToReactiveCommand> </i:EventTrigger> </i:Interaction.Triggers> </Button>
ViewModel側は以下のようになっています。
publicclass EventToReactiveCommandViewModel { public ReactiveCommand<string> SelectFileCommand { get; private set; } public ReactiveProperty<string> Message { get; private set; } public EventToReactiveCommandViewModel() { // command called, after converterthis.SelectFileCommand = new ReactiveCommand<string>(); // create ReactiveProperty from ReactiveCommandthis.Message = this.SelectFileCommand .Select(x => x + " selected.") .ToReactiveProperty(); } }
Windows Runtimeの場合
Windows Runtimeのようにダイアログが非同期呼び出しのケースでは、SelectManyでTaskをIObservableに変換することで、対応することができます。ここらへんRxだとさくっと書けていいですね。
publicclass SelectFileConverter : ReactiveConverter<RoutedEventArgs, string> { protectedoverride IObservable<string> Convert(IObservable<RoutedEventArgs> source) { return source .Select(_ => new FileOpenPicker()) // create picker .Do(x => x.FileTypeFilter.Add(".txt")) // set extensions .SelectMany(x => x.PickSingleFileAsync().AsTask().ToObservable()) // convert task to iobservable .Where(x => x != null) // filter .Select(x => x.Path); // convert } }