我正在努力防止使用带有Xamarin Forms的ReactiveUI双击按钮。假设我们有这样的命令:
NextCommand = ReactiveCommand.CreateFromTask(async () => await HostScreen.Router.NavigateAndReset.Execute(new NewViewModel()));
它以正常的Xamarin Forms方式绑定到一个按钮。不幸的是,非常快的点击导致两个命令调用。
是否可以使用ReactiveUI修复它?
我更新了问题以总结我尝试过的内容:
var obs = Observable.FromAsync(async () => await HostScreen.Router.NavigateAndReset.Execute(new CitizensIndexViewModel()))
.Throttle(TimeSpan.FromSeconds(2));
LoginCommand = ReactiveCommand.CreateFromObservable(() => obs);
不幸的是,它没有帮助。当您在按钮上双击非常快时,将执行两次命令执行。
我还试图将lock语句或信号量添加到'execute'方法,但它也无法工作,因为执行不是并行完成的。这也是使用 CanExecute 方法无效的原因。
可能起作用的是一个丑陋的布尔旗。这个解决方案的唯一问题是我必须在返回导航时重置它,这显然是可行的,但我不认为它是最好的解决方案。
答案 0 :(得分:3)
您可以传递CanExecute参数,该参数将决定是否可以执行该命令。 你可以在Controlling Executability看到:
var canExecute = this
.WhenAnyValue(
x => x.UserName,
x => x.Password,
(u, p) => !string.IsNullOrEmpty(u) && !string.IsNullOrEmpty(p));
var command = ReactiveCommand.CreateFromObservable(this.LogOnAsync, canExecute);
以非常类似的方式,您可以在命令中使用等待指示符:
bool busy = false;
NextCommand = ReactiveCommand.CreateFromTask(
async () =>
{
busy = true;
// do your studd here.
busy = false;
},
!busy);
希望这有帮助。
答案 1 :(得分:1)
var canLogin = this.WhenAnyValue(vm => vm.IsLogingExec, p =>!p);
LoginCommand = ReactiveCommand.CreateFromTask(async () => { this.IsLogingExec = true; await HostScreen.Router.NavigateAndReset.Execute(new CitizensIndexViewModel()); } , canLogin);
.
.
.
private bool isLogingExec;
public bool IsLogingExec{
get => isLoggingExec;
set => this.RaiseAndSetIfChanged(ref isLogingExec, value);
}
canLogin是一个可观察的,根据IsLogingExec值返回true或false。
ReactiveCommand.CreateFromTask有第二个参数,如果命令可以执行,则为true,否则为false。如果无法执行命令,则将禁用带有命令binded的按钮。
执行命令时要做的第一件事是将IsLogingExec更改为false,这样,canLogin将变为false,并且命令按钮将被禁用,然后,它将执行导航方法。
IsLogingExec是一种反应属性,canLogin会对变化作出反应。