GoalsI want to be able to call async code using the MVVM pattern I want tobe able to add loading animations/screens without having to addproperties for each command on my viewmodelsI may want to be able to cancel these operationsThis is what I came up withpublic abstract class CommandBase : ICommand{    private readonly Func<bool> _canExecute;    public CommandBase()    {    }    public CommandBase(Func<bool> canExecute)    {        if (canExecute == null) throw new ArgumentNullException(nameof(canExecute));        _canExecute = canExecute;    }    public bool CanExecute(object parameter)    {        return _canExecute == null || _canExecute();    }    public abstract void Execute(object parameter);    public void RaiseCanExecuteChanged()    {        CanExecuteChanged?.Invoke(this, EventArgs.Empty);    }    public event EventHandler CanExecuteChanged;}public class AsyncCommand : CommandBase, INotifyPropertyChanged{    private readonly Func<CancellationToken, Task> _action;    private CancellationTokenSource _cancellationTokenSource;    private bool _isRunning;    public bool IsRunning    {        get { return _isRunning; }        set        {            _isRunning = value;             OnPropertyChanged();        }    }    private ICommand _cancelCommand;    public ICommand CancelCommand => _cancelCommand ?? (_cancelCommand = new RelayCommand(Cancel));    public AsyncCommand(Func<CancellationToken, Task> action)    {        if (action == null) throw new ArgumentNullException(nameof(action));        _action = action;    }    public AsyncCommand(Func<CancellationToken, Task> action, Func<bool> canExecute) : base(canExecute)    {        if (action == null) throw new ArgumentNullException(nameof(action));        _action = action;    }    private void Cancel()    {        _cancellationTokenSource?.Cancel();    }    public override async void Execute(object parameter)    {        IsRunning = true;        try        {            using (var tokenSource = new CancellationTokenSource())            {                _cancellationTokenSource = tokenSource;                await ExecuteAsync(tokenSource.Token);            }        }        finally        {            _cancellationTokenSource = null;            IsRunning = false;        }    }    private Task ExecuteAsync(CancellationToken cancellationToken)    {        return _action(cancellationToken);    }    public event PropertyChangedEventHandler PropertyChanged;    [NotifyPropertyChangedInvocator]    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)    {        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));    }}It can be used like this:<Button Content=Start Command={Binding UpdateDisplayTextCommand}/><Button Content=Cancel Command={Binding UpdateDisplayTextCommand.CancelCommand}/><ProgressBar IsIndeterminate={Binding UpdateDisplayTextCommand.IsRunning} />Any faults on this implementation? I'm also open to ideas on features which could be added to this class.
AsyncCommand using MVVM and WPF
c#;wpf;mvvm