views:

1221

answers:

4

I have begun creating a wpf mvvm app. It seems a vital ingredient to the ViewModel is a bunch of ICommands to have a loosely coupled way of allowing the view to interact with the viewmodel.

My question is this, why can't I bind directly to a method?

I have used Josh Smith's RelayCommand implementation of ICommand that allows you to inject delgates into an ICommand object, but really, is there some easier way to allow a button push to call a method in the viewmodel?

I'm new to MVVM, I believe I need some enlightenment

+6  A: 

You can't bind directly to a method because Button (for example) doesn't have a property that accepts a delegate. Instead, it has a Command property of type ICommand. A RelayCommand (aka DelegateCommand) is just an ICommand that wraps delegates.

I see no technical reason why it wouldn't be possible for the view to bind to specific methods on the view model by way of a markup extension:

<Button Command="{ViewModelMethod SomeMethodName}"/>

However, this would be slower and would increase the coupling between the view and view model. If the view knows only about a property on the view model of type ICommand, the implementation of that command could change completely (or methods could be renamed) without the view being aware.

HTH, Kent

Kent Boogaart
Why would it be slow? Does it need to use reflection? But I do understand the coupling problem you mentioned.
Jose
Well, actually I don't think it would be much slower, since binding to a viewmodel command also uses reflection. However this approach has a drawback : since that ViewModelCommand markup extension is not a binding, it won't be updated when the ViewModel changes : it will be evaluated only once (unless it hooks to the DataContextChanged event to reevaluate, but that's another story...)
Thomas Levesque
Firstly, I said "slower", not "slow". Important distinction that. Secondly, I was talking about the resolution and invocation of the methods to be called, not the binding itself. Using delegates created by the VM will be quicker than reflectively resolving methods from the view. So on top of all the other draw-backs, doing it from the view would be slower.
Kent Boogaart
+4  A: 

I completely disagree.

The speed of invocation bears no relevance: commands are user interactions, they never require speed.

Argument about coupling is flawed too. How come {Binding MyProperty} is not coupling but {ViewMethod MyMethod} is?

Requirement of having specially crafted 'Commands' to be wrapped around methods is a silly one. Commands might be useful implementation under the cover, but we already have methods in C# and replacing them with something big and bulky is not right.

And that thing about MarkupExtension and Binding, it really is difficult. But it can be done. Actually, it is done, you can have a look at MethodCall project on CodePlex: http://methodcallthing.codeplex.com/

You can use binding to choose 'this' for the method, and can use binding to fetch arguments. And all those are live, i.e. being calculated at the time the command is invoked. Another bonus feature is push-out result of method call, you can use binding for that too (OneWayToSource).

Oleg Mihailik
+2  A: 

ICommand gives you CanExecute, which is needed for control enabling. A simple delegate does not. ICommand is the way to go.

+1  A: 

Apparently Microsoft needed a Command to be something first-class, probably because they felt having the CanExecute was necessary for most applications. I disagree and think the CanExecute should have just been another DependencyProperty that you would bind to a property of your viewmodel, but hey, what do I know?

Possibly they also thought that there was a need to decouple the implementation of a command from the control's datacontext. Yet again this seems unnecessary to me because the logic should live near the data that is being operated on, as is a fundamental principal of OO.

Personally I avoid using commands in MVVM because of the mess you have to create to implement them. I just let the view's code-behind delegate events up to the viewmodel.

Mike Gates