100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
.NET

The ICommand Interface

The core .NET interface that lets ViewModels expose actions to the View without any code-behind, forming the backbone of command-based interaction in MVVM.

CommandsBeginner8 min readJul 10, 2026
Analogies

What Is ICommand?

ICommand lives in the System.Windows.Input namespace and is the contract WPF, UWP, and .NET MAUI use to represent an invokable action as an object rather than a raw event handler. It defines three members: Execute(object parameter), which performs the action; CanExecute(object parameter), which returns a bool telling the UI whether the action is currently valid; and the CanExecuteChanged event, which the framework subscribes to so it knows when to re-query CanExecute. A ViewModel exposes one ICommand property per user action (SaveCommand, DeleteCommand, RefreshCommand) and a View binds a control's Command property to it, completely replacing the Click event handler you would otherwise write in code-behind.

🏏

Cricket analogy: Think of ICommand like the third umpire protocol: Execute is the on-field decision (out or not out) actually being enforced, while CanExecute is the pre-check of whether a review is even available to the captain at that moment, like MS Dhoni deciding whether to burn his last DRS review.

Implementing ICommand from Scratch

Implementing ICommand directly means writing a class that stores two delegates, an Action for Execute and a Func<bool> for CanExecute, and wires CanExecuteChanged to CommandManager.RequerySuggested in WPF so the framework automatically re-checks CanExecute whenever focus changes, a command completes, or the user interacts with the UI. This manual approach is instructive but verbose, which is why almost every real MVVM codebase wraps this boilerplate in a reusable RelayCommand or DelegateCommand class instead of hand-rolling a new ICommand implementation for every single action.

🏏

Cricket analogy: Writing a raw ICommand implementation is like a young club cricketer building their own bowling action from first principles, run-up, load-up, release, follow-through, before later adopting a coach-refined action, the way developers eventually switch to a reusable RelayCommand instead of a bespoke class per action.

csharp
public interface ICommand
{
    void Execute(object parameter);
    bool CanExecute(object parameter);
    event EventHandler CanExecuteChanged;
}

// A minimal hand-written implementation before reaching for RelayCommand
public class SaveDocumentCommand : ICommand
{
    private readonly DocumentViewModel _vm;

    public SaveDocumentCommand(DocumentViewModel vm) => _vm = vm;

    public bool CanExecute(object parameter) => !_vm.IsSaving && _vm.IsDirty;

    public void Execute(object parameter) => _vm.SaveAsync();

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

How the UI Consumes ICommand

Controls that implement ICommandSource, such as Button, MenuItem, and Hyperlink, expose a Command dependency property; when you bind it to a ViewModel's ICommand property, the control automatically calls CanExecute on load and whenever CanExecuteChanged fires, setting IsEnabled accordingly, then calls Execute when clicked, passing whatever is bound to CommandParameter. This means a Save button can grey itself out the instant a document becomes unmodified, with zero code-behind and zero manual IsEnabled wiring, because the plumbing is entirely handled by the ICommandSource contract.

🏏

Cricket analogy: It's like how the third umpire's decision automatically updates the scoreboard and the on-field umpire's signal in sync, no manual radio call needed, the same way a bound Button's IsEnabled state updates itself the instant CanExecuteChanged fires.

In WPF, CommandManager.RequerySuggested piggybacks on common UI events like focus change and mouse clicks to re-query CanExecute globally. This is convenient but can be a performance concern in large views with many commands, which is one reason many teams prefer RelayCommand implementations that raise CanExecuteChanged explicitly.

Binding Command directly to a method group or lambda is not possible in XAML; the bound property must be typed as ICommand. Forgetting to implement CanExecuteChanged correctly is a common bug that leaves buttons permanently enabled or disabled regardless of ViewModel state changes.

  • ICommand is defined in System.Windows.Input and has three members: Execute, CanExecute, and CanExecuteChanged.
  • ViewModels expose ICommand properties instead of event handlers, keeping the View free of code-behind logic.
  • CanExecute returns a bool that WPF uses to automatically enable or disable bound controls.
  • CommandManager.RequerySuggested is the default WPF mechanism that triggers automatic re-evaluation of CanExecute.
  • Controls implementing ICommandSource, like Button and MenuItem, natively understand the Command and CommandParameter properties.
  • Hand-writing ICommand implementations for every action is verbose, motivating reusable helpers like RelayCommand.
  • Correctly raising CanExecuteChanged is essential; forgetting it leaves the UI out of sync with ViewModel state.

Practice what you learned

Was this page helpful?

Topics covered

#NET#MVVMDesignPatternStudyNotes#MicrosoftTechnologies#TheICommandInterface#ICommand#Interface#Implementing#Scratch#StudyNotes#SkillVeris