I'm currently learning WPF and MVVM, I think I get most of it and how it works but I've come across something on using the RelayCommand (or DelegateCommand) that I don't understand. I think it's to do with the way delegates work.
Please note that the code below is all just in test solutions at the moment, so no live code. Also I am considering this for commands that do not require a parameter such as close and to understand why it works.
So if I take the RelayCommand that Josh Smith created( http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030) I can setup a command like this:
RelayCommand updateTextContentCommand;
public ICommand UpdateTextContentCommand
{
get
{
if (updateTextContentCommand == null)
{
updateTextContentCommand = new RelayCommand(
param => this.UpdateTextContentCommand_Execute());
}
return updateTextContentCommand;
}
}
with this execute method:
public void UpdateTextContentCommand_Execute()
{
this.TextContent = DateTime.Now.ToString();
}
I used a simple binding to a TextBlock to see the result and the command is bound to a button. This works fine. What I don't get is the use of the lambda expression to create the command. The Action<object>
expects a parameter doesn't it? so why does this code work?
If I change the code above to
if (updateTextContentCommand == null)
{
updateTextContentCommand = new RelayCommand(
this.UpdateTextContentCommand_Execute());
}
I get these error:
*The best overloaded method match for 'MVVM.RelayCommandTesting.Framework.RelayCommand.RelayCommand(System.Action)' has some invalid arguments
Argument 1: cannot convert from 'void' to 'System.Action'*
and removing the ()
after Execute gives this error:
Argument 1: cannot convert from 'method group' to 'System.Action'
But if I change the code like this:
if (updateTextContentCommand == null)
{
updateTextContentCommand = new RelayCommand(
this.UpdateTextContentCommand_Execute);
}
public void UpdateTextContentCommand_Execute(object param)
{
this.TextContent = DateTime.Now.ToString();
}
it complies and runs fine. If I change the view to use CommandParameter I can then use param to set the text content using this method but if I use the lambda style I have to pass a parameter to the line so its like this param => this.UpdateTextContentCommand_Execute(param)
.
In my test I'm hard coding the CommandParameter value but I guess it would most likely be data bound to a property of the ViewModel in a real system so you would be able to pass the parameter in the lambda style.
Can anyone explain why the parameterless version works with the lambda style please?
Thanks for taking the time to read this.
It seems the question below had some questions about the lambda as well but I don't see that it answers my question.
Passing a parameter using RelayCommand defined in the ViewModel (from Josh Smith example)