MiF.RelayCommand 1.0.0

dotnet add package MiF.RelayCommand --version 1.0.0
                    
NuGet\Install-Package MiF.RelayCommand -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MiF.RelayCommand" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MiF.RelayCommand" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="MiF.RelayCommand" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MiF.RelayCommand --version 1.0.0
                    
#r "nuget: MiF.RelayCommand, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MiF.RelayCommand@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MiF.RelayCommand&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=MiF.RelayCommand&version=1.0.0
                    
Install as a Cake Tool

MiF.RelayCommand

Tiny, dependency-free ICommand implementations for MVVM on .NET. Provides both synchronous and asynchronous relay commands with strong typing and optional concurrency control.

Goal

Offer simple, fast, and strongly-typed ICommand helpers for MVVM (WPF/WinUI/MAUI), covering both sync and async scenarios without external dependencies.

Features

  • .NET 9, zero-dependency library.
  • Commands included:
    • RelayCommand (Action)
    • RelayCommand<T> (Action<T>)
    • AsyncRelayCommand (Func<Task>)
    • AsyncRelayCommand<T> (Func<T, Task>)
  • Optional CanExecute predicates and RaiseCanExecuteChanged().
  • Async commands can block reentrancy: allowConcurrentExecutions flag + IsExecuting.
  • Strict parameter typing and nullability-aware checks for T.
  • Thread-safe execution state tracking.

Installation

  • CLI: dotnet add package MiF.RelayCommand
  • Visual Studio: Project > Manage NuGet Packages� then search for �MiF.RelayCommand�.

Usage

using MiF.RelayCommand;
using System.Windows.Input;

// -------------------------------
// Synchronous commands (RelayCommand)
// -------------------------------
public sealed class PersonViewModel
{
    public ICommand SaveCommand { get; }
    public ICommand DeleteCommand { get; }

    private bool _canSave;
    public bool CanSave
    {
        get => _canSave;
        set
        {
            if (_canSave == value) return;
            _canSave = value;
            // Notify UI as usual, then update CanExecute:
            (SaveCommand as RelayCommand)?.RaiseCanExecuteChanged();
        }
    }

    public PersonViewModel()
    {
        SaveCommand = new RelayCommand(
            execute: Save,
            canExecute: () => CanSave);

        DeleteCommand = new RelayCommand<Guid>(
            execute: DeleteById,
            canExecute: id => id != Guid.Empty);
    }

    private void Save()
    {
        // persist changes
    }

    private void DeleteById(Guid id)
    {
        // delete by id
    }
}
// XAML (example):
// <Button Content="Save" Command="{Binding SaveCommand}" />
// <Button Content="Delete"
//         Command="{Binding DeleteCommand}"
//         CommandParameter="{Binding SelectedItemId}" />
// -------------------------------
// Asynchronous commands (AsyncRelayCommand)
// -------------------------------
public sealed class OrdersViewModel
{
    public ICommand LoadCommand { get; }
    public ICommand UpdateCommand { get; }

    public OrdersViewModel()
    {
        // No reentrancy while executing (button disabled during run)
        LoadCommand = new AsyncRelayCommand(
            executeAsync: LoadAsync,
            canExecute: () => true,
            allowConcurrentExecutions: false);

        // Parameterized async command with validation
        UpdateCommand = new AsyncRelayCommand<int>(
            executeAsync: UpdateOrderAsync,
            canExecute: id => id > 0,
            allowConcurrentExecutions: false);
    }

    private async Task LoadAsync()
    {
        // load data asynchronously
        await Task.Delay(200);
    }

    private async Task UpdateOrderAsync(int orderId)
    {
        // update order asynchronously
        await Task.Delay(200);
    }
}
// XAML (example):
// <Button Content="Load" Command="{Binding LoadCommand}" />
// <Button Content="Update"
//         Command="{Binding UpdateCommand}"
//         CommandParameter="{Binding SelectedOrderId}" />

Notes

  • RelayCommand/RelayCommand<T>: Call RaiseCanExecuteChanged() when conditions (like CanSave) change.
  • AsyncRelayCommand/AsyncRelayCommand<T>: With allowConcurrentExecutions = false, the command disables itself during execution. RaiseCanExecuteChanged() is automatically invoked before and after execution.
  • Generic commands validate parameter type and allow null only when T is a reference or nullable type.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 134 8/20/2025