Is there any difference between these ICommand implementations?

Emon Haque 3,176 Reputation points
2020-10-28T05:07:20.457+00:00

One way I've seen is this:

public class Command : ICommand
{
    Action<object> execute;
    Func<object, bool> canExecute;
    public Command(Action<object> execute, Func<object, bool> canExecute)
    {
        this.canExecute = canExecute;
        this.execute = execute;
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public bool CanExecute(object parameter) => canExecute(parameter);
    public void Execute(object parameter) => execute(parameter);     
}

and the other I'm using is:

public class Command : ICommand
{
    Action<object> execute;
    Func<object, bool> canExecute;
    public Command(Action<object> execute, Func<object, bool> canExecute)
    {
        this.canExecute = canExecute;
        this.execute = execute;
        CommandManager.RequerySuggested += (o, e) => OnCanExecuteChanged();
    }
    public event EventHandler CanExecuteChanged;
    public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(null, EventArgs.Empty);
    public bool CanExecute(object parameter) => canExecute(parameter);
    public void Execute(object parameter) => execute(parameter);     
}

are both of these correct?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,690 questions
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,306 Reputation points
    2020-10-28T13:53:38.723+00:00

    Hi,
    try following demo and you can see RemoveHandler when Button will be destroyed.

    XAML MainWindow:

    <Window x:Class="WpfApp1.Window010"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp010"  
            mc:Ignorable="d"  
            Title="Window010" Height="450" Width="800">  
      <Window.DataContext>  
        <local:ViewModel/>  
      </Window.DataContext>  
      <StackPanel>  
        <Button Content="Change UC" Command="{Binding Cmd}" CommandParameter="ChangeUC"/>  
        <ContentControl Content="{Binding UC}"/>  
      </StackPanel>  
    </Window>  
    

    ViewModel and RelayCommand:

    using System;  
    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Input;  
    using WpfControlLibrary1;  
      
    namespace WpfApp010  
    {  
      public class ViewModel : INotifyPropertyChanged  
      {  
        public UserControl UC { get; set; }  
        public ICommand Cmd { get => new RelayCommand(CmdExec, CanCmdExec); }  
        private void CmdExec(Object parameter)  
        {  
          switch (parameter.ToString())  
          {  
            case "ChangeUC":  
              UC = new Window010UC1();  
              OnPropertyChanged(nameof(UC));  
              break;  
            default:  
              break;  
          }  
        }  
        private bool CanCmdExec(object obj) => true;  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));  
      }  
      
      public class RelayCommand : ICommand  
      {  
        private readonly Predicate<object> _canExecute;  
        private readonly Action<object> _action;  
        public RelayCommand(Action<object> action) { _action = action; _canExecute = null; }  
        public RelayCommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }  
        public void Execute(object o) => _action(o);  
        public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);  
        public event EventHandler CanExecuteChanged  
        {  
          add { CommandManager.RequerySuggested += value; }  
          remove { CommandManager.RequerySuggested -= value; }  
        }  
      }  
    }  
    

    XAML UserControl:

    <UserControl x:Class="WpfControlLibrary1.Window010UC1"  
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
                 xmlns:local="clr-namespace:WpfControlLibrary1"  
                 mc:Ignorable="d"   
                 d:DesignHeight="450" d:DesignWidth="800">  
      <Grid>  
        <Button Content="Button in UserControl" Command="{Binding Cmd}"/>  
      </Grid>  
    </UserControl>  
    

    Result:

    35669-x.gif

    2 people found this answer helpful.

0 additional answers

Sort by: Most helpful