2017-07-03 46 views
0

我在MVVM應用程序上工作,並試圖使用文本框文本更改註冊表來運行一個命令,每當此文本框發生新的更改時都可以取消該命令。 在無擴展它與交換機的方法是這樣完成的:ReactiveUI與RestApi的CancelableCommand

Observable.FromEventPattern<PropertyChangedEventArgs>(this, nameof(PropertyChanged)) 
      .Where(a => a.EventArgs.PropertyName == nameof(Item)) 
      .Select(a => Item) 
      .DistinctUntilChanged() 
      .Throttle(TimeSpan.FromSeconds(0.5)) 
      .ObserveOn(SynchronizationContext.Current) 
      .Do(x => { Items= null; }) 
      .ObserveOn(Scheduler.Default) 
      .Select(item => { return Observable.FromAsync(cancellationToken => _itemService.GetItemsAsyncWithCancelation(item, cancellationToken)); }) 
      .Switch() 
      .ObserveOn(SynchronizationContext.Current) 
      .Subscribe(items => Items = items); 

當我嘗試做同樣的事情ReactiveUi這就是我想出迄今:

public ReactiveCommand GetItemsCommand { get; set; } 
GetTowaryCommand = ReactiveCommand 
     .CreateFromTask<string>(async (x,cancelationToken) => Items = await _itemService.GetItemsAsyncWithCancelation(x.ToString(),cancelationToken)); 

this.WhenAnyValue(vm => vm.Item) 
     .Throttle(TimeSpan.FromSeconds(0.5)) 
     .Do(_=> GetTowaryCommand.Dispose()) 
     .ObserveOn(SynchronizationContext.Current) 
     .InvokeCommand(GetItemsCommand); 

這是工作,但我不知道如果RestApi電話被正確取消。 我試圖遵循ReactiveUI文檔例如: https://docs.reactiveui.net/en/user-guide/commands/canceling.html 但不知道如何字符串參數(X)傳遞給RESTAPI方法:

GetItemsCommand 
    .CreateFromObservable<string>(() => Observable.StartAsync(async (token) => Items = await _itemService.GetItemsAsyncWithCancelation(x.ToString(), token))) 

回答

0

因爲我不知道究竟是什麼具體問題在這裏是的,我會試着看看我能在這裏做什麼。

將您的GetItemsCommand更改爲類型ReactiveCommand<string, Unit>(進去,Unit熄滅)。然後,你可以說:

GetItemsCommand.CreateFromObservable<string,Unit>(x => 
    Observable.StartAsync(async (token) => 
     Items = await _itemService.GetItemsAsyncWithCancelation(x.ToString(), token))) 

InvokeCommand會自動在參數傳遞給命令,如果有一個可用的(即Observable.Return("hello").InvokeCommand(GetItemsCommand)將通過「打招呼」的命令),所以你可能需要修改任何代碼調用GetItemsCommand

作爲一個側面說明,您可以通過在命令的Subscribe塊從命令返回一個列表和設置Items財產在一個稍微乾淨分離的-關注還挺方式改寫這個:

public ReactiveCommand<string, IEnumerable<T>> GetItemsCommand { get; set; } 

GetItemsCommand.CreateFromObservable<string, IEnumerable<T>>(x => 
    Observable.FromAsync(token => 
     _itemService.GetItemsAsyncWithCancelation(x.ToString(), token))); 

// always runs on UI thread 
GetItemsCommand.Subscribe(x => Items = x); 

此外,您通常不應該手動撥打ReactiveCommand.Dispose(您鏈接的文檔在訂閱,而不是在命令)。通過CancellationToken或設置另一個observable來取消運行命令(兩者都在您的鏈接中)通常是最簡單的方法。

例如:

var stream = this.WhenAnyValue(vm => vm.Item) 
    .Throttle(TimeSpan.FromSeconds(0.5)) 
    .DistinctUntilChanged(); 

stream 
    .InvokeCommand(GetItemsCommand); 

GetItemsCommand.CreateFromObservable<string, IEnumerable<T>>(x => 
    Observable 
     .FromAsync(token => _itemService.GetItemsAsyncWithCancelation(x.ToString(), token)) 
     .TakeUntil(stream)); 

GetItemsCommand.Subscribe(x => Items = x); 

沒有實際測試過這個最後一點,但我覺得它應該工作:)只是一些想法。

+0

我想我現在明白了。非常感謝。 – mdziadowiec