using System; using System.Threading.Tasks; using System.Windows.Input; namespace MVVM { public class ActionCommandAsync : ICommand { private Func action; private Predicate predicate; private bool executing = false; public ActionCommandAsync(Func action) : this(action, null) { } public ActionCommandAsync(Func action, Predicate predicate) { this.action = action ?? throw new ArgumentNullException(nameof(action)); this.predicate = predicate; } #region ICommand members: public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) => !executing && (predicate == null || predicate(parameter)); public void Execute() => Execute(null); public async void Execute(object parameter) { var task = action(parameter); if (task != null) { executing = true; await task; executing = false; } } #endregion } }