using System.Windows.Input; namespace JdeScoping.SecureStoreManager.ViewModels; /// /// An async command implementation that properly handles async operations. /// public class AsyncRelayCommand : ICommand { private readonly Func _execute; private readonly Func? _canExecute; private bool _isExecuting; private EventHandler? _canExecuteChanged; /// /// Raised when the result of CanExecute() may have changed. /// public event EventHandler? CanExecuteChanged { add => _canExecuteChanged += value; remove => _canExecuteChanged -= value; } /// /// Creates a new AsyncRelayCommand that can always execute. /// /// The async action to execute. public AsyncRelayCommand(Func execute) : this(execute, null) { } /// /// Creates a new AsyncRelayCommand with a CanExecute predicate. /// /// The async action to execute. /// The predicate to determine if the command can execute. public AsyncRelayCommand(Func execute, Func? canExecute) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } /// /// Determines whether the command can be executed in its current state. /// /// The command parameter (unused). public bool CanExecute(object? parameter) { return !_isExecuting && (_canExecute?.Invoke() ?? true); } /// /// Executes the async command if it can execute. /// /// The command parameter (unused). public async void Execute(object? parameter) { if (!CanExecute(parameter)) return; _isExecuting = true; RaiseCanExecuteChanged(); try { await _execute(); } finally { _isExecuting = false; RaiseCanExecuteChanged(); } } /// /// Raises the CanExecuteChanged event. /// public void RaiseCanExecuteChanged() { _canExecuteChanged?.Invoke(this, EventArgs.Empty); } }