ICommand Interface and RelayCommand Class in WPF MVVM
ICommand Interface and RelayCommand Class in WPF are commonly used for binding. ICommand Interface and RelayCommand class is implemented in the ViewModel and is exposed to the view controls.
Every view in the app has an empty codebehind file, except for the standard code that calls InitializeComponent in the class's constructor. In fact, you could remove the views' codebehind files from the project and the application would still compile and run correctly. Despite the lack of event handling methods in the views, when the user clicks on buttons, the application reacts and satisfies the user's requests. This works because of bindings that were established on the Command property of Hyperlink, Button, and MenuItem controls displayed in the UI. Those bindings ensure that when the user clicks on the controls, ICommand objects exposed by the ViewModel execute. You can think of the command object as an adapter that makes it easy to consume a ViewModel's functionality from a view declared in XAML.
When a ViewModel exposes an instance property of type ICommand, the command object typically uses that ViewModel object to get its job done.
We will try to understand ICommand Interface and RelayCommand Class with following example.
Create a View and ViewModel like following:
View: Lets create the view first. Three things to note in this view
1. In this view, I have included MyWPFSample namespace
xmlns:local="clr-namespace:MyWPFSample"
2. I have set datacontext of the winodw to the MainWindowViewModel class present in MyWPFSample namespace
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
3. I have done binding of the command of the button with the ButtonCommand property of MainWindowViewModel class.
Command="{Binding ButtonCommand}"
<Window x:Class="MyWPFSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWPFSample"
Title="MainWindow" Height="150" Width="370">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Button Content="Click"
Height="23"
HorizontalAlignment="Left"
Margin="77,45,0,0"
Name="btnClick"
VerticalAlignment="Top"
Width="203"
Command="{Binding ButtonCommand}"
CommandParameter="Hai" />
</Grid>
</Window>
ViewModel: ViewModel has namespace MyWPFSample, class as MainWindowViewModel and property as ButtonCommand.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;
namespace MyWPFSample
{
class MainWindowViewModel
{
private ICommand m_ButtonCommand;
public ICommand ButtonCommand
{
get
{
return m_ButtonCommand;
}
set
{
m_ButtonCommand = value;
}
}
public MainWindowViewModel()
{
ButtonCommand=new RelayCommand(new Action<object>(ShowMessage));
}
public void ShowMessage(object obj)
{
MessageBox.Show(obj.ToString());
}
}
}
When the user clicks on buttons, the application reacts and satisfies the user's requests. This works because of bindings that were established on the Command property of Button displayed in the UI. The command object acts as an adapter that makes it easy to consume a ViewModel's functionality from a view declared in XAML.
RelayCommand Class
In this example RelayCommand class is used for implementing ICommad object. I think it's a simple and standard approach.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace MyWPFSample
{
class RelayCommand : ICommand
{
private Action<object> _action;
public RelayCommand(Action<object> action)
{
_action = action;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
if (parameter != null)
{
_action(parameter);
}
else
{
_action("Hello World");
}
}
#endregion
}
}
ICommand and RelayCommand keep track whether or not commands are available. If commands are not available, then all controls associated with that command are disabled. For example using command controls like button can be disabled if CanExecute() returns false. The Code that executes when command is invoked and is located in Execute event. handler.