ちまちまとした拡張メソッドだけではなく、こんな感じでIInteractionRequestを実装したクラスを作ってしまうのもありかも??まだ、スケジューラとかについては何も考えてないけど、とりあえずのやっつけで・・・。
namespace Okazuki.KinkumaFramework.ReactiveProperty { using System; using System.Reactive.Linq; using System.Reactive.Subjects; using Microsoft.Practices.Prism.Interactivity.InteractionRequest; using System.Reactive.Disposables; public static class InteractionRequestExtensions { public static ReactiveInteractionRequest<T> ToReactiveInteractionRequest<T>(this IObservable<T> self) where T : Notification { return new ReactiveInteractionRequest<T>(self); } } public class ReactiveInteractionRequest<T> : IInteractionRequest, IObservable<T>, IDisposable where T : Notification { private SingleAssignmentDisposable disposable = new SingleAssignmentDisposable(); private Subject<T> subject = new Subject<T>(); public ReactiveInteractionRequest(IObservable<T> o) { this.disposable.Disposable = o.Subscribe(n => { this.OnRaised(n); }); } public ReactiveInteractionRequest() : this(Observable.Never<T>()) { } public event EventHandler<InteractionRequestedEventArgs> Raised; private void OnRaised(T t) { var h = this.Raised; if (h != null) { h(this, new InteractionRequestedEventArgs(t, () => { subject.OnNext(t); })); } } public IObservable<T> Raise(T n) { this.OnRaised(n); return this.AsObservable(); } public IDisposable Subscribe(IObserver<T> observer) { return this.subject.Subscribe(observer); } public void Dispose() { if (this.disposable.IsDisposed) { return; } this.subject.OnCompleted(); this.disposable.Dispose(); } } }
こうすると、IObservable
// 普通 this.EditCommand .Subscribe(_ => { var vm = new EditWindowViewModel(this.SelectedItem.Value); this.ShowEditWindowRequest.Raise( new Notification { Title = vm.EditTargetViewModel.Value.Name.Value + " Editing", Content = vm }, n => { // ここにいろいろ処理をかく }); });
// 前回のコード this.EditCommand // InteractionRequest経由で編集画面を表示 .SelectMany(_ => // ShowEditWindowRequestはInteractionRequest<Notification>型のプロパティ // XAML側でウィンドウを表示するTriggerActionと紐づけてるイメージ this.ShowEditWindowRequest.RaiseAsObservable( new Notification { Title = vm.EditTargetViewModel.Value.Name.Value + " Editing", Content = new EditWindowViewModel(this.SelectedItem.Value) })) .Subscribe(n => { var vm = n.Content as EditWindowViewModel; // 結果を受けて何なりと処理をやる // 主にModelへの委譲 });
// 今回の場合 this.ShowEditWindowRequest = this .EditCommand .Select(_ => new Notification { Title = "編集", Content = new EditWindowViewModel(this.SelectedItem.Value) }) .ToReactiveInteractionRequest(); this.ShowEditWindowRequest.Subscribe(n => { var vm = n.Content as EditWindowViewModel; // ここにいろいろな処理を書く });
それっぽくなってきたかもしれん?