使用ReactiveUI

时间:2017-10-06 14:27:08

标签: xamarin mvvm xamarin.forms reactiveui

我正在努力防止使用带有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 方法无效的原因。

可能起作用的是一个丑陋的布尔旗。这个解决方案的唯一问题是我必须在返回导航时重置它,这显然是可行的,但我不认为它是最好的解决方案。

2 个答案:

答案 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会对变化作出反应。