Category Archives: Command Binding

This category discussed about the Concept of Command Binding in .NET aling with the implementation of ICommand interface

Basics of Command Binding Using ICommand

ICommand is used to define a command. The interface contains the following information.

public interface ICommand
{
    //has 2 methods
    void Execute(object parameter);
    bool CanExecute(object parameter);

    //1 event
    event EventHandler CanExecuteChanged;
}

ICommand interface consists of the following:

Two methods:
CanExecute : Defines the method that determines whether the command can execute in its current state.
Execute : Defines the method to be called when the command is invoked.

One Event:
CanExecuteChanged: Occurs when changes occur that affect whether or not the command should execute.

You implement the ICommand interface on a class, provide a way for command handlers to hook up, and then do the routing when the command is invoked. You also must decide what criteria you will use for determining when to raise the CanExecuteChanged event. Using custom ICommand implementations allows us to provide our own routing mechanisms, particularly ones that are not tied to the visual tree and that can support multiple command handlers. Given an instance of an ICommand, you just call Execute, and it does whatever it’s supposed to do. Except you shouldn’t call it if it’s CanExecute is false. If you want to know when CanExecute might be willing to give you a different answer, listen to the CanExecuteChanged event.

Lets try a simple hello world application using the IComand. First, declare a class derived from ICommand and name it as MyFirstCommand. Since the class MyFirstCommand is derived from ICommand, we need to implement the interface as shown below. Whenever the command is executed, it calls the Execute() method to show a Hello World message box.

public class MyFirstCommand : ICommand
{
    public void Execute(object parameter)
    {
        MessageBox.Show("Hello world");
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }
    public event EventHandler CanExecuteChanged;
}

 

Once you have an ICommand instance handy, you can give it to a Button (on the Button.Command property), and Button knows what to do with it. As the simplest example, you can do this with the previous command:

First, we need to create get the class namespace into XAML using the following code. To know more about Instantiating an Object as a resource in XAML see the link https://kishore1021.wordpress.com/2010/02/06/instantiating-an-object-as-a-resource-in-xaml/

xmlns:local="clr-namespace:CommandBinding2"

 

Create a resource in the Grid class as shown below.

<Grid.Resources>
            <local:MyFirstCommand x:Key="hwc"/>
        </Grid.Resources>

Create a button inside the grid and assign the resource we created in the above code to the button command property.

Button Content="Hello World" Height="36" HorizontalAlignment="Left" Margin="12,115,0,0" Name="button1" VerticalAlignment="Top" Width="116"
                Command="{StaticResource hwc}"/>
   

 

If you do that, you’ll notice that the Button is enabled. In the CanExecute() method, if we have not returned true, then the button would have appeared as disabled. That’s because Button knows to call CanExecute, but we haven’t specified a parameter, and recall from above that if you pass null as an argument to CanExecute it returns false. So Button has a CommandParameter property that lets you specify what will be passed to CanExecute and Execute:

Now the button is enabled, and if you click on it, you’ll see “Hello, world” in the debug output window.

This actually isn’t just a Button feature, it’s actually in the base class ButtonBase. And MenuItem is a ButtonBase. So MenuItem can use the ICommand too. If MenuItem’s Command property is set to the Static resource hwc, it will also behave the same.

Passing parameter to the Command

Lets go through the hello world code discussed above and change it a bit to use the command parameters. In the Button class, set the CommandParameter property to some text like “Hello, World” as shown in the following code.

<Button Content="Hello World" Height="36" HorizontalAlignment="Left" Margin="12,115,0,0" Name="button1" VerticalAlignment="Top" Width="116"
                CommandParameter="Hello, World"
                Command="{StaticResource hwc}"/>
    

 

In the code file, change the Execute() method to show the parameter passed to the command. Modify the CanExecute() method to return true if the command parameter contains a value otherwise return false as shown in the following code.

public class MyFirstCommand : ICommand
{
    public void Execute(object parameter)
    {
        MessageBox.Show(parameter.ToString());
    }

    public bool CanExecute(object parameter)
    {
        if (parameter != null)
            return true;
        else
            return false;
    }
    public event EventHandler CanExecuteChanged;
}

 

Run the project and see the magic yourself.

Going further with ICommand:

 

image

Figure 1: Class diagram of the participating classes

A good starting point for creating a custom command is to use delegates. A delegate already supports invocation of a target method, and it also supports multiple subscribers. In the above diagram, have a student class and a UISaveCommand class that the MainWindow uses. The idea is that when I click on Save Button as shown in Fig 2, it should call the Save() method. But the Button Command doesn’t know where the Save() method is present. So the UISaveCommand class uses the Func<>.

image

Figure 2: Output window

Step 1:

Let us create a UISaveCommand class derived from ICommand interface and implement the interface in that class as shown below. In the CanExecute() method we are checking to see if the function pointer (funcpointer) is pointing to a valid or not. If it points to a valid function, we return true otherwise return false. The Execute() method just calls the method pointed to by the function pointer (delegate).

public class UISaveCommand : ICommand
{
    public Func<int> funcpointer
    {
        get;
        set;
    }

    public bool CanExecute(object parameter)
    {
        if (funcpointer != null)
        {
            return true;
        }
        else
            return false;

        throw new NotImplementedException();
    }

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

    public void Execute(object parameter)
    {
        if (funcpointer != null)
        {
            funcpointer();
        }

    }
}

Func<> is declared as public delegate TResult Func<out TResult>(); It encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter. In the MainWindow class, create an object of UISaveCommand class and assign the funcpointer to Save() method as shown below. So we are binding the method present in one class from other place using Command.

public partial class MainWindow : Window
{
    Student stobj = new Student();

   public MainWindow()
    {
        InitializeComponent();
        
        UISaveCommand savecommand = new UISaveCommand();
        savecommand.funcpointer = Save;
        stobj.StudentClassCommand = savecommand;
        this.DataContext = stobj;
    }

   public int Save()
   {
       MessageBox.Show(stobj.FirstName + stobj.LastName);
       return 0;
   }
}

Then we assign the savecommand object to the Student class property of type ICommand. Following is the code of the Student class.

public class Student : INotifyPropertyChanged
    {
       public ICommand StudentClassCommand
       {
           get;
           set;
       }

        private string firstname;

        public string FirstName
        {
            get { return firstname; }
            set
            {
                firstname = value;
                OnPropertyChanged("FirstName");
            }
        }

        private string lastname;

        public string LastName
        {
            get { return lastname; }
            set
            {
                lastname = value;
                OnPropertyChanged("LastName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
    }

The complete code of .CS file is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace CommandBinding2
{
    public class MyFirstCommand : ICommand
    {
        public void Execute(object parameter)
        {
            MessageBox.Show(parameter.ToString());
        }

        public bool CanExecute(object parameter)
        {
            if (parameter != null)
                return true;
            else
                return false;
        }
        public event EventHandler CanExecuteChanged;
    }

    public class UISaveCommand : ICommand
    {
        public Func<int> funcpointer
        {
            get;
            set;
        }

        public bool CanExecute(object parameter)
        {
            if (funcpointer != null)
            {
                return true;
            }
            else
                return false;

            throw new NotImplementedException();
        }

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

        public void Execute(object parameter)
        {
            if (funcpointer != null)
            {
                funcpointer();
            }

        }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Student stobj = new Student();

       public MainWindow()
        {
            InitializeComponent();
            
            UISaveCommand savecommand = new UISaveCommand();
            savecommand.funcpointer = Save;
            stobj.StudentClassCommand = savecommand;
            this.DataContext = stobj;
        }

       public UISaveCommand savecommand
       {
           get
           {
               throw new System.NotImplementedException();
           }
           set
           {
           }
       }

       public int Save()
       {
           MessageBox.Show(stobj.FirstName + stobj.LastName);
           return 0;
       }
    }

   public class Student : INotifyPropertyChanged
    {
       public ICommand StudentClassCommand
       {
           get;
           set;
       }

        private string firstname;

        public string FirstName
        {
            get { return firstname; }
            set
            {
                firstname = value;
                OnPropertyChanged("FirstName");
            }
        }

        private string lastname;

        public string LastName
        {
            get { return lastname; }
            set
            {
                lastname = value;
                OnPropertyChanged("LastName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
    }

    ////public class StringDelegateCommand : ICommand
    ////{
    ////    Action<string> m_ExecuteTargets = delegate { };
    ////    Func<bool> m_CanExecuteTargets = delegate { return false; };
    ////    bool m_Enabled = false;

    ////    public bool CanExecute(object parameter)
    ////    {
    ////        Delegate[] targets = m_CanExecuteTargets.GetInvocationList();
    ////        foreach (Func<bool> target in targets)
    ////        {
    ////            m_Enabled = false;
    ////            bool localenable = target.Invoke();
    ////            if (localenable)
    ////            {
    ////                m_Enabled = true;
    ////                break;
    ////            }
    ////        }
    ////        return m_Enabled;
    ////    }
        
    ////    public void Execute(object parameter)
    ////    {
    ////        if (m_Enabled)
    ////            m_ExecuteTargets(parameter != null ? parameter.ToString() : null);
    ////    }
        
    ////    public event EventHandler CanExecuteChanged = delegate { };

    ////    public event Action<string> ExecuteTargets
    ////    {
    ////        add { m_ExecuteTargets += value; }
    ////        remove { m_ExecuteTargets -= value; }
    ////    }

    ////    public event Func<bool> CanExecuteTargets
    ////    {
    ////        add { m_CanExecuteTargets += value; CanExecuteChanged(this, EventArgs.Empty); }
    ////        remove { m_CanExecuteTargets -= value; CanExecuteChanged(this, EventArgs.Empty); }
    ////    }
    ////}
}

 

The complete code of XAML file is

<Window x:Class="CommandBinding2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:CommandBinding2"
        Title="MainWindow" Height="282" Width="474">
    <Grid Height="295" Width="440">
        <Grid.Resources>
            <local:MyFirstCommand x:Key="hwc"/>
        </Grid.Resources>

        <TextBlock Text="Enter First Name" Margin="0,0,271,261"></TextBlock>
        <TextBox Margin="175,6,12,260" Name="txtFirstName" VerticalAlignment="Center" Text="{Binding Path=FirstName}" Height="26" />
        <TextBlock Margin="0,48,324,216" VerticalAlignment="Center" Text="Enter Last Name" Height="28" />
        <TextBox Margin="175,55,12,215" Name="txtLastName" VerticalAlignment="Center" Text="{Binding Path=LastName}"/>
        <Button Margin="187,102,0,144" Content="Save"
                Command="{Binding StudentClassCommand}" />
        <Button Content="Hello World" Height="36" HorizontalAlignment="Left" Margin="12,115,0,0" Name="button1" VerticalAlignment="Top" Width="116"
                CommandParameter="Hello, World"
                Command="{StaticResource hwc}"/>
    </Grid>
</Window>

 

Attitude determines altitude. – Anonymous
Advertisements

Introduction to Command Binding

We have seen the abc’s of Data Binding here. If you have worked in VC++, then you are aware of some of the semantics of WPF command binding. Basically, commands are nothing but actions performed on the applications using input mechanism. commands are abstract and loosely-coupled version of events. Whereas events are tied to details about specific user actions (such as a Button being clicked or a List Item being selected), commands represent actions independent from their user interface exposure. Canonical examples of commands are Cut, Copy, and Paste. In VC++ MFC, we declare commands and then define the functions that execute the command action. Similarly, in WPF, the semantics and the object that invokes a command is separated from the logic that executes the command. This allows for multiple and disparate sources like MenuItems in a Menu, MenuItems on a Context Menu(Right Click), Buttons on a ToolBar, keyboard shortcuts(CTRL+X for Cut), and so on, to invoke the same command logic, and it allows the command logic to be customized for different targets. We used to perform similar design in VC++ too.

In VC++ MFC application, for example, the editing operations Copy, Cut, and Paste, can be invoked by using different user actions if they are implemented by using commands. An MFC application might allow a user to cut selected text by either choosing an Cut item in edit menu, or Cut in right click menu, or using a key combination, such as CTRL+X. By using commands, you can bind each type of user action to the same logic. In VC++, we assign ID’s to each command like ID_EDIT_COPY, ID_EDIT_CUT and ID_EDIT_PASTE. WPF supports similar concepts but uses a different mechanism to achieve it. By using commands, you can bind each type of user action to the same logic. Another purpose of commands is to indicate whether an action is available. To continue the example of cutting an object or text, the action only makes sense when something is selected. If a user tries to cut an object or text without having anything selected, nothing would happen. To indicate this to the user, many applications disable buttons and menu items so that the user knows whether it is possible to perform an action.

A command is any object implementing the ICommand interface (from System.Windows.Input), which defines two methods and one event:

  • Execute—The method that executes the command-specific logic
  • CanExecute—A method returning true if the command is enabled or false if it is disabled
  • CanExecuteChanged—An event that is raised whenever the value of CanExecute changes

Steps to create a Command:

  1. Say you want to create a Cut Command. We need to implement a class that implements ICommand.
  2. Call Execute from relevant event handlers (when CanExecute returns true)
  3. Handle the CanExecuteChanged event to toggle the IsEnabled property on the relevant pieces of user interface.

Fortunately, controls such as Button, CheckBox, and MenuItem have logic to interact with any command on your behalf. They expose a simple Command property (of type ICommand). When set, these controls automatically call the command’s Execute method (when CanExecute returns true) whenever their Click event is raised. In addition, they automatically keep their value for IsEnabled synchronized with the value of CanExecute by leveraging the CanExecuteChanged event. By supporting all this via a simple property assignment, all of this logic is available from XAML. Some of WPF’s controls have built-in behavior tied to various commands. 

WPF’s built-in commands like Cut, Copy, Paste are exposed as static properties and they are all instances of RoutedUICommand, a class that not only implements ICommand, but supports bubbling just like a routed event. A command can indicate whether an action is possible by implementing the CanExecute method. A button can subscribe to the CanExecuteChanged event and be disabled if CanExecute returns false or be enabled if CanExecute returns true.

WPF defines a bunch of commands already, so you don’t have to implement ICommand objects for Cut, Copy, and Paste and worry about where to store them. WPF’s built-in commands are exposed as static properties of five different classes:

  • ApplicationCommands—Close, Copy, Cut, Delete, Find, Help, New, Open, Paste, Print, PrintPreview, Properties, Redo, Replace, Save, SaveAs, SelectAll, Stop, Undo, and more
  • ComponentCommands—MoveDown, MoveLeft, MoveRight, MoveUp, ScrollByLine, ScrollPageDown, ScrollPageLeft, ScrollPageRight, ScrollPageUp, SelectToEnd, SelectToHome, SelectToPageDown, SelectToPageUp, and more
  • MediaCommands—ChannelDown, ChannelUp, DecreaseVolume, FastForward, IncreaseVolume, MuteVolume, NextTrack, Pause, Play, PreviousTrack, Record, Rewind, Select, Stop, and more
  • NavigationCommands—BrowseBack, BrowseForward, BrowseHome, BrowseStop, Favorites, FirstPage, GoToPage, LastPage, NextPage, PreviousPage, Refresh, Search, Zoom, and more
  • EditingCommands—AlignCenter, AlignJustify, AlignLeft, AlignRight, CorrectSpellingError, DecreaseFontSize, DecreaseIndentation, EnterLineBreak, EnterParagraphBreak, IgnoreSpellingError, IncreaseFontSize, IncreaseIndentation, MoveDownByLine, MoveDownByPage, MoveDownByParagraph, MoveLeftByCharacter, MoveLeftByWord, MoveRightByCharacter, MoveRightByWord, and more

Each of these properties does not return a unique type implementing ICommand. Instead, they are all instances of RoutedUICommand, a class that not only implements ICommand, but supports bubbling just like a routed event.

image

Lets develop a dialog that has a “Help” button, when clicked will open the help webpage. Let’s demonstrate how these built-in commands work by attaching some logic with the Help command defined in ApplicationCommands. Assuming the Button is named helpButton, you can associate it with the Help command in C# as follows:

helpButton.Command = ApplicationCommands.Help;

All RoutedUICommand objects define a Text property containing a name for the command that’s appropriate to show in a user interface. (This property is the only difference between RoutedUICommand and its base RoutedCommand class.) For example, the Help command’s Text property is (unsurprisingly) set to the string Help. The hard-coded Content on this Button could therefore be replaced as follows:

helpButton.Content = ApplicationCommands.Help.Text;

If you were to run the dialog with this change, you would see that the Button is now permanently disabled. That’s because the built-in commands can’t possibly know when they should be enabled or disabled, or even what action to take when they are executed. They delegate this logic to consumers of the commands. To plug in custom logic, you need to add a CommandBinding to the element that will execute the command or any parent element (thanks to the bubbling behavior of routed commands). All classes deriving from UIElement (and ContentElement) contain a CommandBindings collection that can hold one or more CommandBinding objects. Therefore, you can add a CommandBinding for Help to the dialog’s root Window as follows in

<Window.CommandBindings>
        <CommandBinding Command="Help"
                        CanExecute="CommandBinding_CanExecute"
                        Executed="CommandBinding_Executed" />
    </Window.CommandBindings>

 

Or in its code-behind file:

this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Help,
        CommandBinding_Executed, CommandBinding_CanExecute));

The methods called CommandBinding_Executed and CommandBinding_CanExecute have to be defined in code behind file as follows. These methods will be called back at appropriate times in order to plug in an implementation for the Help command’s CanExecute and Execute methods.

private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    if (firstName.Text == "help")
        e.CanExecute = true;
    else
        e.CanExecute = false;

}

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
    System.Diagnostics.Process.Start("https://kishore1021.wordpress.com/&quot;);

}

 

In the XAML file, assign the command to the help button as follows.

<Button Grid.Row="3" Grid.Column="1" Command="Help"
          Name="MyHelpButton" Margin="4,190,0,5">
            Help
        </Button>

 

Compile the project and run the application. Initially, the help button is disabled. Enter help in the first name textbox and you can see that the help button is enabled. Now to take advantage of command binding, say you want to bring up help when user presses keyboard shortcut F2 key. We can bind our own input gestures to a command by adding KeyBinding and/or MouseBinding objects to the relevant element’s InputBindings collection in code as follows

this.InputBindings.Add(
              new KeyBinding(ApplicationCommands.Help, new KeyGesture(Key.F2)));

The same binding can be performed in XAML as follows

<Window.InputBindings>
    <KeyBinding Command="Help" Key="F2"/>
    <KeyBinding Command="NotACommand" Key="F1"/>
</Window.InputBindings>

 

The complete XAML code is

<Window x:Class="CommandBinding101.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525">
    <Window.CommandBindings>
        <CommandBinding Command="Help"
                        CanExecute="CommandBinding_CanExecute"
                        Executed="CommandBinding_Executed" />
    </Window.CommandBindings>
    <Window.InputBindings>
        <KeyBinding Command="Help" Key="F2"/>
        <KeyBinding Command="NotACommand" Key="F1"/>
    </Window.InputBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label>
            Enter your first name:
        </Label>
        <TextBox Grid.Row="0" Grid.Column="1"
           Name="firstName" Margin="0,5,10,5"/>

        <Label Grid.Row="1" >
            Enter your last name:
        </Label>
        <TextBox Grid.Row="1" Grid.Column="1"
           Name="lastName" Margin="0,5,10,5"/>

        <Button Grid.Row="2" Grid.Column="0"
          Name="Clear" Margin="2" Click="Clear_Click">
            Clear Name
        </Button>

        <Button Content="Enable Help" Margin="2" Name="button1" Grid.Column="1" Grid.Row="2" Click="button1_Click" />
        
        <Button Grid.Row="3" Grid.Column="1" Command="Help"
          Name="MyHelpButton" Margin="4,190,0,5">
            Help
        </Button>
        <Label Content="Type help in the first name edit box to enable the Help button" Margin="-1,13,12,164" Grid.Row="3" Grid.ColumnSpan="2" />
    </Grid>
    
</Window>

The complete code behind is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CommandBinding101
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //MyHelpButton.Command = ApplicationCommands.Help;

           // this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Help,
           //  CommandBinding_Executed, CommandBinding_CanExecute));

            //this.InputBindings.Add(
            //  new KeyBinding(ApplicationCommands.Help, new KeyGesture(Key.F2)));

        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (firstName.Text == "help")
                e.CanExecute = true;
            else
                e.CanExecute = false;

        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://kishore1021.wordpress.com/&quot;);

        }

        private void Clear_Click(object sender, RoutedEventArgs e)
        {
            firstName.Clear();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            firstName.Text = "help";
        }
    }
}

If you use one of the preexisting RoutedUICommand objects for a WPF command, e.g. ApplicationCommands.Open, you’ll notice that the RoutedUICommand instance has a Text property.  This property in the command is used to set the label appearing on any MenuItem instances that have attached to the command by setting their Command property.  You don’t need to set the menu item’s Header property explicitly.

Download the source code here

If you really want the key to success, start by doing the opposite of what everyone else is doing.