In application using a mvvm-approach it's pretty common that the ViewModel provides one or more Command-properties. These properties often have the type ICommand or DelegateCommand or something like that.
I don't understand why we need such an approach in an mvvm application. Wouldn't it be enough to provide public methods and bind the action from the view directly to this public method?
Why does ICommand exist?
Wouldn't it be enough to provide public methods and bind the action from the view directly to this public method? Why ICommand exists?
you can't bind to a method in xaml. You need an object. Therefore you need to wrap the method to an object.
it is a common pattern in UI, that some actions are not available all the time. In Login form the Login action become available only when you enter username. In MS Word, the Copy or Cut actions becomes available only when you select something, otherwise the buttons are disabled and keyboard shortcuts inactive
Plain eventhandlers does not meet those requirements, But ICommand
servers exactly those purposes:
public interface ICommand
{
void Execute(object parameter);
bool CanExecute(object parameter);
event EventHandler CanExecuteChanged;
}
Now, let's consider Copy&Paste scenario. Using ICommand the markup can look like this:
<Button Content="Paste" Command="{Binding PasteCommand}" />
<MenuItem Header="Paste" Command="{Binding PasteCommand}" />
public ICommand PasteCommand {get;} = new DelegateCommand(Paste, () => Clipboard != null);
How would it look like without ICommand
? To make it easier, lets consider, that XAML would allow to bind to methods:
<Button Content="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}" />
<MenuItem Header="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}"/>
public void Paste() {....}
private bool _canPaste;
public bool CanPaste
{
get { return _canPaste }
set
{
if (_canPaste != value)
{
_canPaste = value;
OnNotifyPropertyChanged(nameof(CanPaste);
}
}
}
as you can see, not only it is more verbose, but it's also violation of DRY principle. You need to specify both Paste
and CanPaste
binding every time you want to use the command. What if you started without CanPaste and later you wanted to add it. Then you would have to add the CanPaste binding every occurrence of the Paste
call. I guarantee you, that you would forget it somewhere.
Now, if you did this in WPF:
<Button Content="Paste" Click="Call_ViewModel_Paste" />
//in codebehind:
void Call_ViewModel_Paste(oobject sender, RoutedEventArgs e)
{
ViewModel.Paste();
}
or eventually:
<Button Content="Paste">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction MethodName="Paste" TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Both approaches are correct, they follow MVVM priciples and works without ICommand, but as you can see, neither is as elegant as ICommand