I am using ReactiveUI
with AvaloniaUI
and have a ViewModel with several ReactiveCommands
namely Scan, Load, and Run.
Scan is invoked when an Observable<string>
is updated (when I receive a barcode from a scanner).
Load is triggered from within the Scan command.
Run is triggered from a button on the UI.
Simplified code below:
var canRun = Events.ToObservableChangeSet().AutoRefresh().ToCollection().Select(x => x.Any());
Run = ReactiveCommand.CreateFromTask<bool>(EventSuite.RunAsync, canRun);
var canLoad = Run.IsExecuting.Select(x => x == false);
var Load = ReactiveCommand.CreateFromTask<string, Unit>(async (barcode) =>
{
//await - go off and load Events.
}, canLoad);
var canReceiveScan = Load.IsExecuting.Select(x => x == false)
.Merge(Run.IsExecuting.Select(x => x == false));
var Scan = ReactiveCommand.CreateFromTask<string, Unit>(async (barcode) =>
{
//do some validation stuff
await Load.Execute(barcode)
}, canReceiveScan);
Barcode
.SubscribeOn(RxApp.TaskpoolScheduler)
.ObserveOn(RxApp.MainThreadScheduler)
.InvokeCommand(Scan);
Each command can only be executed if no other command is running (including itself). But I can't reference the commands' IsExecuting
property before is it declared. So I have been trying to merge the "CanExecute" observable variables like so:
canRun = canRun
.Merge(Run.IsExecuting.Select(x => x == false))
.Merge(Load.IsExecuting.Select(x => x == false))
.Merge(Scan.IsExecuting.Select(x => x == false))
.ObserveOn(RxApp.MainThreadScheduler);
// same for canLoad and canScan
The issue I'm having is that the ReactiveCommand will continue to execute when another command is executing.
Is there a better/correct way to implement this?