2017-10-06 63 views
2

我努力防止使用Xamarin Forms使用ReactiveUI雙擊按鈕。假設我們有這樣的命令:使用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); 

不幸的是,它並沒有幫助。當你在一個按鈕上快速雙擊時,會執行兩次命令執行。

我也嘗試添加鎖定語句或信號到'execute'方法,但它也失敗了,因爲執行並不是並行完成的。這也是爲什麼使用CanExecute方法不起作用的原因。

潛在的工作是一個醜陋的布爾標誌。這個解決方案唯一的問題是我不得不在重新導航時重置它,這顯然是可行的,但我不認爲它是最好的解決方案。

+1

這聽起來不對。 https://github.com/reactiveui/ReactiveUI/blob/f23538577ea7e567ab372c550adebebe9fdbb7f7/src/ReactiveUI/ReactiveCommand.cs#L566 在此問題中沒有足夠的信息可以回答。通常的方式是什麼?你的實現是什麼樣的。請提供一個repro。 –

+0

@GeoffreyHuntley我更新了我的問題。我希望我的意思更清楚。我對ReactiveUI相當陌生,所以請原諒我的無知:)。我只想學習 – mierzynskim

回答

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); 

希望這有助於。

+0

查看我更新的問題。也許使用CanExecute是一條正確的道路,但即使你用bool標誌來阻止它,下一個執行也不會並行完成,並且會成功執行 – mierzynskim

+0

你試圖用CanExecute調試你的代碼嗎?你真的看到CanExecute爲第二次點擊返回true嗎?執行死刑意味着什麼不是平行進行的?如果您爲CanExecute使用isBusy,則應在首次單擊後立即禁用按鈕。沒有發生? –

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是一個observable,根據IsLogingExec值返回true或false。

ReactiveCommand.CreateFromTask具有第二個參數,如果該命令可以執行則返回true,否則返回false。如果命令無法執行,綁定命令的按鈕將被禁用。

命令在執行時執行的第一件事是將IsLogingExec更改爲false,這樣就可以將LoginLog更改爲false,並禁用commandbutton,然後執行導航方法。

IsLogingExec是一種反應性屬性,這就是canLogin會對變化做出反應的方式。