WPF: MVVM: Command vs CallMethodAction? - wpf

I'm learning the MVVM pattern with a new(small) project, and I've one question about the way to invoke actions on our controller:
I saw many tutorial where they were telling us to use Command, implying to declare a RelayCommand, initialize it and create the action called by the RelayCommand.
In the other side, I've a colleague which said me that I can use the CallMethodAction with a trigger:
<i:Interaction.Triggers>
<i:EventTrigger>
<ei:CallMethodAction MethodName="Init" TargetObject="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
For me, his approach has the advantage that I don't have to make some inits methods for commands(which may be never used).
So what am I missing? Why everybody use commands?

Commands are out-of-the-box solution and can be attached only to elements which implement the ICommand interface. On the other hand, event triggers can be attached to any event, what makes them more flexible. I follow the general strategy to use Commands where user interactions are involved (buttons, menus) and CanExecute pattern is needed. My commands are strictly connected to visual interface (provide caption, image source, etc.). I use CallMethodAction in any other situation when I want to get rid of code-behind.

Commands provide functionality for disabling in ViewModel code. That can be used to automatically disable e.g buttons bound to command. That's what makes Commands better. Besides, based on your logic you could just dynamically pluck another Command in the same slot and it will reroute the traffic from View, whereas in CallMethodAction you would have to write the rerouting logic in the called method, which would be ugly.
As you can see, it depends on what you try to accomplish and how complicated is your logic :)

Related

Is there a better way than handling CommandBindings in code behind?

I have an application using MVVM. I'm trying to Intercept key presses on an MCE Remote control for Play, Pause, Stop etc....
Currently I'm using command bindings with a method in the code behind performing the related action on a media element as such
<Window.CommandBindings>
<CommandBinding Command="MediaCommands.Play" Executed="PlayMediaElement"/>
<CommandBinding Command="MediaCommands.Stop" Executed="StopMediaElement"/>
</Window.CommandBindings>
Before trying to include the remote control functionality I had approx 10 view-models/views with nothing in code behind.
I'm wondering if there is a better way to do this so I retain the MVVM pattern or is it perfectly acceptable/preferable to implement in this way.
EDIT - I've moved the Command Bindings from a UserControl inside a View into my MainWindow.xaml and placed the methods into MainWindow.xaml.cs. MainWindow doesn't have a view/viewmodel relationship, simply a content control with a ViewModel linked to it.
In my code behind methods I'm making use of a Mediator to send messages (Play,Pause,Stop etc...) to my mediaplayerviewmodel which in turn interacts with it's respective view. Is this a good idea or is there a better way?
I think Josh Smith created a huge confusion in his 2009 article, when he made a point that his code-behind CS files remained mostly empty. MVVM is not about not having code-behind. It is about separation of concerns. If there is any practical rule you should follow, is to make the ViewModel view agnostic (i.e. no reference from the ViewModel to the View. Think having a second unit test implementation of a 'View' for your ViewModel).
This "no code behind" confusion caused very odd structures just to work arround a problem that shouldn't have existed to begin with.
Having code behind in the MainWindow.xaml.cs is perfectly reasonable solution, as long as you don't have logic there, but simply forward the call to an appropriate method in the View Model. If that was my code I would have created custom commands (a la DelegateCommand from the same article) that binds directly to commands in the ViewModel, but your design is 100% legit as well.
Head over to Codeplex.com and look for Caliburn (or better Caliburn Micro). It extends WPF to actually allow calling of methods with arbitrary parameters pulled from other objects and the method being in the view model / controller without having a "hook method" in code behind just fowwarding the call.
The extensions can do wonderfull thignsl ike pull the value of a textbox and pass it as parameter to a method, then react on the return value - much like a view should.
You run in a limitation of "stock" wpf - which simply can only point towards method handlers in code behind without any regards to parameters. Alterantives exist, even from microsoft.

Standalone Command Objects in WPF

Is it possible / practical to implement WPF commands as standalone objects? If so, how is this typically done? Most of the examples I see about commanding typically involve using RoutedCommand, RoutedUICommand, or some other implementation of ICommand like RelayCommand. The way these commands work in the MVVM pattern is to expose an instance of one of these types of commands through a property. Inside the ViewModel, the logic for the command is implemented as a method on the ViewModel and then passed as a delegate to the command object.
The "classic" Command pattern as I understand it would be to have each command implemented as it's own standalone object, such as an OpenCustomerViewCommand. Since the logic would be completely encapsulated in its own object, it could potentially be reused in other parts of my app. For example, if I could open the CustomerView from several places in my app it might be helpful to be able to simply create an instance of the OpenCustomerViewCommand on each ViewModel where the CustomerView could be accessed, rather than copy and paste that method into each ViewModel, and pass the delegate to a RelayCommand. If I understand correctly, the predefined ApplicationCommands such as Cut and Paste behave this way.
To me, having to provide the logic inside the ViewModel seems to diminish the value of the command pattern a bit. I suppose I don't really understand the major difference between doing it this way, and having a code behind that implements command handlers for UI events. Is there any reason I should be using the RoutedCommand pattern over the more classic approach I described above?
You could do this, but it requires some method of routing the request appropriately.
In your example, provided the OpenCustomerViewCommand knows how and where to open the "Customer View", you could easily reuse this anywhere. Instead of using a class like RelayCommand, you can just implement ICommand directly and add your logic to do this.
The problem, however, is that most commands tend to be more of an adapter for xaml to execute ViewModel-specific functionality. In most applications on which I've worked, there tend to be few commands that really need the reuse - most commands are tied to functionality specific to the ViewModel in question. As such, something like RelayCommand makes hooking this up fairly easy.

Control events into commands and RX

We have some WPF/Silverlight controls we have written using the traditional event architecture (no commands etc.), and want to convert it to MVVM compliant ones. I researched on this subject, and i take it i will have to write commands to wrap the events that i currently have in the control. I would like to design it correctly now so i want to also make it RX complaint, rather than just commands.
Can someone explain to me how i can design my currently designed events into commands and RX ones please.
It will be useful if we took something like a control's Click event, and design command for it, and also RX compliant (observable, etc.), so i can understand what is involved.
Currently it is simple events, its pretty simple to understand to work with it :)... so one can subscribe to it and execute custom handlers.
My employer wants me to make this commands and also RX-ify it.
I read some articles on these, but found it to require some PhD degree to understand (mathematical Dual, Subject<T>, etc.) :) I could not get my heads around it.
I am struggling to taking this and making it into commands and also into RX. Please help. I want to learn this properly, so i don't have to re-design it again once more.
Thanks in advance.
Paul D,
I think you may be just forcing technology for technology sake.
First you want to use the Command pattern in WPF/SL so that you can write testable code (MVVM). This is independent of Rx. If you have your ViewModel constructed correctly then if you choose to use Rx somewhere else (Repository, Model, Controllers etc) then great.
The reason that WPF uses commands instead of the Event pattern is because a command tells something to happen, where as an event broadcasts that something did happen. When you write a Control it is fine for you to broadcast that a Click occured, but in you ViewModel a command reflects that something should happen.
If we look at an example:
a SubmitOrderCommand may initiate a call to submit the state of the Model to a repository. This in itself does not need to involve Rx. The progress of the Submission however, may utilise Rx to publish the state changes eg Submitting-->Submitted-->CreditChecked-->Accepted.
This may then result in a some contracts that look like this (psuedo code)
class OrderEntryViewModel
{
public ICommand SubmitOrderCommand { get; }
}
interface IOrderRepository
{
IObservable<OrderStatus> SubmitOrder(SubmitOrderRequest request);
}
I agree with you that there is way too much Academia around Rx. I recomment that you check out my blog introduction to Rx. I hope it helps you grasp Rx much faster.
UPDATE: Check out my book IntroToRx.com instead. It replaces the blog series.
I have no idea about ReactiveXaml but if you want to bind events to command, I could advise you MVVM light. You can try something similar to the code below, moreover MVVM light is provided with an EventToCommand Sample:
<Window
...
xmlns:Interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
/>
<ComboBox ItemSource="{Binding MyCollection}">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding Path=LoadCommand}" />
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</ComboBox>

Relay/Delegate Command & InputGestures

I want to have a command from my view model associated with F8, and don't know a great deal about input gestures. Must I wrap it in a routed command or is there another recommended way to do this?
Cheers,
Berryl
UPDATE
My original posting really had two pain points in them. The first was that prior to WPF 4 you couldn't bind a command directly to an input gesture or count on visual inheritance for the command's DataContext, and had to go through a CommandManager layer. That seems like the reason the MVVM Toolkit's CommandReference that NVM pointed out was useful, but now with WPF 4 this is fixed as the Command is an attached DP on the InputBinding, so all you need to do is something like:
<DataGrid.InputBindings>
<KeyBinding Command="{Binding MyViewModel.MyCommand}" Key="F8" />
</DataGrid.InputBindings>
The second pain point to realize is that binding an input gesture to a command is not the same as associating the textual representation of that gesture to a menu item. So I need to do something like:
<MenuItem Header="{x:Static s:Strings.MyHeaderString}" Command="{Binding MyViewModel.MyCommand}"
InputGestureText="F8"/>
I spelled this out in the hopes that someone will either tell me I've got something wrong (or right). Assuming this is the best you can do then it's down to how much DRYness you can get and how to do that while keeping strictly visual elements out of your ViewModels. You could do this either by having some properties on your Command (ie, KeyGesture, KeyModifier) or having the "F8" in a resource file I suppose, depending on how much you need to reuse something and your point of view. Also on how many input gestures you have for the command!
How do I associate a keypress with a DelegateCommand in Composite WPF?
This is your answer. Instead of Key="X" you should use Gesture="F8"

What is the real advantage of keeping code out of the XAML code behind?

There is a lot of effort in the Silverlight community to keep a XAML's code behind file as free of code as possible. What is the real motivation behind this?
For example, what is the advantage of using a command instead of an event handler? If I have
<Button x:Name="SaveButton" Content="Save" Click="SaveButton_Click" />
...
private void SaveButton_Click(object sender, RoutedEventArgs e) {
_myViewModel.SaveChanges();
}
Then why is this prefered?
<Button x:Name="SaveButton" Content="Save" Command="{Binding SaveCommand}" />
Where obviously the SaveCommand in my view model is effectively going to invoke SaveChanges().
This can lead to situations where the view is 100% XAML, even instantiating the view model in XAML, and the connections between the view and view model are completely done through binding. Sure it's clean, but what else is it? Flexible? Why? the view still needs to work with the proper ViewModel, so if the connection between the two exists and is implicit, why not make it more explicit? It also has the disadvantage of losing compile time support. If I hook my button up to an event handler that doesn't exist, the compiler will tell me. It won't if I bind to a non-existent command.
There is a lot of effort in the
Silverlight community to keep a XAML's
code behind file as free of code as
possible. What is the real motivation
behind this?
I would say that people who want the code behind "as free of code as possible" are those who have jumped on the MVVM bandwagon without really getting the point. (Either that or you have misinterpreted their point).
The point is not to keep the code-behind free of code, but to make sure that the View is only responsible for visual presentation. That fact that many visual aspects can be defined declaratively means there is less code in the code-behind, but it does not mean you should hesitate to write code-behind where you feel it is necessary and does not transgress outside the view's responsibilities.
what is the advantage of using a
command instead of an event handler?
A Command offers at least two capabilities that an event handler doesn't. Some WPF controls are aware of the CanExecute property of the Command, so for example a button can be disabled when the command is not available to execute. Also the designer and binding framework are Command aware.
If you just want to call a method on a button press there is no great advantage to using Commands instead of just calling the method from an event handler. So don't be afraid to use this approach. (A third approach, which favours designer over programmer, is to use the CallMethodAction from Blend 4).
It makes unit testing and / or TDD easier. By using MVVM and commanding, I can essentially build my view model and commands TDD style and have most of the view logic tested without actually having the XAML view at all.
There are probably many arguments you might hear for it but pragmatically there is only one, testability. A ViewModel delivers little unless you build a unit test for it, which in turn implies that you would need to create the ViewModel in such a way that you can unit test it, using techniques such as dependency injection, IoC, blah, blah, etc, etc.
The result is that unit tests can cover a larger part of your applications code than you could achieve had you kept the UI code more integrated.
I'm not necessarily recommending it, to do it properly takes considerable design effort and forethought. Hence the costs in building such an approach are quite high, however, the savings of the increased quality may well offset those costs.
The main advantage I see with the command is when you have the dual requirement of executing an action and validating that the action can execute (i.e. context). In other words, if you are simply linking the click with a straight method call, I agree, I see no advantage either. If the click should be conditioned, however, and the button disabled based on context, then the binding facilitates this through the CanExecute property.
This way, instead of having to worry about controls in the view (i.e. having the logic that says "find this control, and set it to disabled because we can't execute it right now) we can create a command and simply ensure that can execute returns false. This is testable independent of the view and once you do bind it, the binding itself takes care of managing the control's enabled property.

Resources