using System.Windows.Input; namespace MossyUpdater.ViewModels { public class RelayCommand : ICommand { private readonly Action _execute; private readonly Predicate? _canExecute; public RelayCommand(Action execute, Predicate? canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public RelayCommand(Action execute, Func? canExecute = null) : this(_ => execute(), canExecute == null ? null : _ => canExecute()) { } public event EventHandler? CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object? parameter) { return _canExecute?.Invoke(parameter) ?? true; } public void Execute(object? parameter) { _execute(parameter); } public void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); } } public class AsyncRelayCommand : ICommand { private readonly Func _execute; private readonly Predicate? _canExecute; private bool _isExecuting; public AsyncRelayCommand(Func execute, Predicate? canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public AsyncRelayCommand(Func execute, Func? canExecute = null) : this(_ => execute(), canExecute == null ? null : _ => canExecute()) { } public event EventHandler? CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object? parameter) { return !_isExecuting && (_canExecute?.Invoke(parameter) ?? true); } public async void Execute(object? parameter) { if (!CanExecute(parameter)) return; try { _isExecuting = true; RaiseCanExecuteChanged(); await _execute(parameter); } finally { _isExecuting = false; RaiseCanExecuteChanged(); } } public void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); } } }