// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.Toolkit.Mvvm.ComponentModel; namespace Microsoft.Toolkit.Mvvm.Input { /// /// A generic command that provides a more specific version of . /// /// The type of parameter being passed as input to the callbacks. public sealed class AsyncRelayCommand : ObservableObject, IAsyncRelayCommand { /// /// The to invoke when is used. /// private readonly Func execute; /// /// The optional action to invoke when is used. /// private readonly Func? canExecute; /// public event EventHandler? CanExecuteChanged; /// /// Initializes a new instance of the class that can always execute. /// /// The execution logic. public AsyncRelayCommand(Func execute) { this.execute = execute; } /// /// Initializes a new instance of the class that can always execute. /// /// The execution logic. /// The execution status logic. public AsyncRelayCommand(Func execute, Func canExecute) { this.execute = execute; this.canExecute = canExecute; } private Task? executionTask; /// public Task? ExecutionTask { get => this.executionTask; private set => SetAndNotifyOnCompletion(ref executionTask, () => executionTask, value); } /// public void NotifyCanExecuteChanged() { CanExecuteChanged?.Invoke(this, EventArgs.Empty); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool CanExecute(T parameter) { return this.canExecute?.Invoke(parameter) != false; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool CanExecute(object parameter) { return CanExecute((T)parameter); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Execute(T parameter) { ExecuteAsync(parameter); } /// public void Execute(object parameter) { ExecuteAsync((T)parameter); } /// public Task ExecuteAsync(T parameter) { if (CanExecute(parameter)) { return ExecutionTask = this.execute(parameter); } return Task.CompletedTask; } /// public Task ExecuteAsync(object parameter) { return ExecuteAsync((T)parameter); } } }