我正在努力使用ReactiveUI用例,我觉得这很简单,必须有开箱即用的#34;支持它。但我找不到它。
该场景是具有以下功能的基本搜索界面:
搜索应该像这样:
基本上我试图扩展"令人信服的例子"在开始新命令之前取消当前正在执行的命令。
似乎很容易?是的,但我无法使用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
不可靠,因为它假设命令的串行操作。我无法使用InvokeCommand
代替Execute
,因为在搜索过程中不会启动新的搜索。
我目前有一个没有ReactiveCommand
的工作解决方案。但我强烈认为应该使用ReactiveCommand
以简单的方式支持这个简单的用例。我错过了什么?
答案 0 :(得分:3)
AFAICT Rx7并没有真正处理这种重叠执行。所有消息最终都会通过,但不会使您的IsExecuting始终如一。 Rx6使用了飞行计数器,因此处理了重叠的执行,但Rx7将其简化为一切。最有可能的是性能和可靠性(但我只是在猜测)。因为任务不会立即取消第一个命令将在第二个命令启动后完成,这导致IsExecuting从true切换为false,从true切换为true。但是当消息赶上时,从false到true到false的中间转换会立即发生。我知道你说你有一个非反应命令工作,但这是一个我认为与反应命令一起工作的版本,等待第一个命令完成或完成取消。等到任务实际取消的一个好处是你确信你没有两只手在饼干罐里:-)在你的情况下这可能无关紧要,但在某些情况下可能会很好。
//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);