/// <summary> /// If no canExecute deletage is provided, CanExecute allows a single simultaneous command execution /// </summary> /// <param name="parameter">Ignored; this is the paremeterless command class</param> /// <returns></returns> public bool CanExecute(object parameter = null) { try { return(canExecute != null?canExecute() : executingCount == 0); } catch (Exception ex) { XLog.Trace(ex); return(true); } }
// Asynchronous command handling based on http://stackoverflow.com/a/31595509/6043538 public async void Execute(object?parameter = null) { var couldExecuteBeforeExecute = CanExecute(); if (!couldExecuteBeforeExecute) { return; } Interlocked.Increment(ref executingCount); var couldExecuteDuringExecute = CanExecute(); if (couldExecuteDuringExecute != couldExecuteBeforeExecute) { RaiseCanExecuteChanged(); // TODO: test if always raising canexecutechanged does not disturb normal UI element update during a short synchronous command. If so, keep preventing multiple execution but only raise CanExecuteChanged for asynchrounous commands } try { if (execute != null) { execute(); } else if (asyncExecute != null) { await asyncExecute(); } else { throw new Exception("Execute is null"); } } catch (Exception ex) { XLog.Trace(ex); } finally { Interlocked.Decrement(ref executingCount); var couldExecuteAfterExecute = CanExecute(); if (couldExecuteAfterExecute != couldExecuteDuringExecute) { RaiseCanExecuteChanged(); } } }