2017-03-08 30 views
2

私はReactiveUIの使用例に苦労しています。これは簡単なことですが、「すぐに使える」サポートが必要です。しかし、私はそれを見つけることができません。ユーザが検索テキスト ReactiveCommandのキャンセルと再実行

  • を結果することを示す
  • インジケータを提示される結果テキストボックスに入る

    • 検索文字列のテキストボックス:

      シナリオでは、これらの機能を備えた基本的な検索インターフェースであります

      :検索では、検索は次のように動作するはず進行

    であります0

  • 検索文字列TextBoxが抑制され、 の500ms後に検索操作が開始されます。
  • 新しい検索が開始されるたびに、進行中の検索操作をキャンセルする必要があります。
  • 基本的には、新しいコマンドを開始する前に、現在実行中のコマンドをキャンセルするための「説得力のある例」を拡張しようとしています。

    十分に簡単ですか?ええ、ReactiveCommandを使って正しく取得することはできません。これは私が持っているものです:

    var searchTrigger = this.WhenAnyValue(vm => vm.SearchString) 
        .Throttle(TimeSpan.FromMilliseconds(500)) 
        .Publish().RefCount(); 
    var searchCmd = ReactiveCommand.CreateFromObservable(
        () => Observable 
         .StartAsync(ct => CancellableSearch(SearchString, ct)) 
         .TakeUntil(searchTrigger)); 
    searchCmd.ToPropertyEx(this, vm => vm.Result); 
    searchCmd.IsExecuting.ToPropertyEx(this, vm => vm.IsSearching); 
    searchTrigger.Subscribe(_ => searchCmd.Execute(Unit.Default).Subscribe()); 
    

    上記のコードはsearchCmd.IsExecuting以外のすべての面で機能します。 searchCmd.CanExecuteの状態に関係なく、私は新しい検索を開始します。これにより、コマンドのシリアル操作を前提としているので、IsExecutingは信頼できません。 Executeの代わりにInvokeCommandを使用することはできません。検索が進行中であるため、新しい検索が開始されないためです。

    私は現在、ReactiveCommandのない実用的な解決策を持っています。しかし、私はこの単純なユースケースがReactiveCommandを使って簡単にサポートされるべきだと強く感じています。私は何が欠けていますか?

    答えて

    3

    AFAICT Rx7では、この種のオーバーラップ実行は実際には処理されません。すべてのメッセージは結局通り抜けますが、IsExecutingを一貫して真実に保つ方法ではありません。 Rx6はIn飛行カウンターを使用していたので、重複した実行は処理されましたが、Rx7はすべての方法を簡略化しました。パフォーマンスと信頼性が高いと思われます(しかし、私はちょうど推測しています)。タスクが即座にキャンセルされることはないため、2番目のコマンドの実行後に最初のコマンドが完了し、IsExecutingがtrueからfalseにtrueからfalseに切り替わります。しかし、真偽から真偽への真の移行は、メッセージが追いつくにつれて直ちに起こります。私は非反応司令部が働いていると言ったことは知っていますが、ここでは最初のコマンドが完了するのを待つか、または取り消しを完了するのを待って反応型コマンドで動作すると思われるバージョンです。タスクが実際にキャンセルするまで待つことの利点の1つは、クッキージャーに2つの手がないことを保証していることです.-あなたのケースでは問題にならないかもしれないが、場合によってはうまくいくかもしれません。

    //Fires an event right away so search is cancelled faster 
    var searchEntered = this.WhenAnyValue(vm => vm.SearchString) 
        .Where(x => !String.IsNullOrWhiteSpace(x)) 
        .Publish() 
        .RefCount(); 
    
    
    
    ReactiveCommand<string, string> searchCmd = ReactiveCommand.CreateFromObservable<string, string>(
        (searchString) => Observable.StartAsync(ct => CancellableSearch(SearchString, ct)) 
            .TakeUntil(searchEntered)); 
    
    //if triggered wait for IsExecuting to transition back to false before firing command again 
    var searchTrigger = 
        searchEntered 
         .Throttle(TimeSpan.FromMilliseconds(500)) 
         .Select(searchString => searchCmd.IsExecuting.Where(e => !e).Take(1).Select(_ => searchString)) 
         .Publish() 
         .RefCount(); 
    
    _IsSearching = 
        searchCmd.IsExecuting 
        .ToProperty(this, vm => vm.IsSearching); 
    
    
    searchTrigger 
        .Switch() 
        .InvokeCommand(searchCmd); 
    
    +1

    偉大な答え。ありがとう。実際に操作をシリアライズすることはオプションです。しかし、取り消しが完了するまでに時間がかかることがあるので、私は進行中の操作について「忘れて」いるだけで、すぐに新しいものを開始することを好むでしょう。 –

    関連する問題