How or when to cleanup RelayCommand objects in WPF/MVVM? - wpf

I am using the standard Josh Smith implementation of RelayCommand to implement ICommands in my WPF/MVVM application. See: WPF Apps with the MVVM Design Pattern
A few of my CanExecute methods take a long time to run. Individually, they aren't bad (a fraction of a second each). But I have noticed that the more commands that I bind to my UI, the slower the application responds (delays exceeding 10 seconds - yuck).
I believe it is because the RelayCommand CanExecuteChanged is hooking onto the CommandManager.RequerySuggested event and my ViewModel template calls CommandManager.InvalidateRequerySuggested() as part of the IDataErrorInfo validation.
My ViewModels implement IDisposable, so I have tried to take advantage of the OnDispose method to clean up my RelayCommands, but the ICommand.CanExecute methods continue to be called even after my VM is disposed of.
That leads me to conclude that something (the CommandManager?, the View?) is holding a reference to the RelayCommand.
Does anyone have a good pattern for releasing and disposing of RelayCommands to prevent them from being requeried after their desired lifetime has expired?
Is there a better way to manage when CanExecute should be called?

You can take out the CommandManager.RequerySuggested and use MVVM Light's RelayCommand implementation. Note: this requires you to explicitly call RaiseCanExecuteChanged() anytime you want CanExecute to be updated.

Related

Commands in MVVM

I've been seeing tutorials where people are creating the methods like CanExecute in their code. I'm assuming they are doing this to help the reader understand how it all works. When I look up Command and ICommand it takes me to the ICommand class on MSDN that is used for Windows Store apps. Is there not a Command class for WPF?
The built-in implementation of ICommand in WPF is RoutedCommand (and its sibling RoutedUICommand). RoutedCommand works like this:
The Execute and CanExecute methods on a RoutedCommand do not contain
the application logic for the command as is the case with a typical
ICommand, but rather, these methods raise events that traverse the
element tree looking for an object with a CommandBinding. The event
handlers attached to the CommandBinding contain the command logic.
The problem with this is that these event handlers must be attached to the code-behind for your view, which is exactly what you do not want to do in MVVM.
Tutorials where you see CanExecute methods in code (and by that we really mean code outside the ICommand implementation) are using custom command implementations such as DelegateCommand and RelayCommand which are designed to "forward" their CanExecute/Execute logic to functions provided on the fly; typically, those are methods on the viewmodel that exposes the command.
These implementations are usually provided by MVVM frameworks (for these two examples the frameworks are Prism and MVVM Light respectively), but they are really simple (both are open source, grab the code and read it) and there's nothing stopping you from copy/pasting the code if you don't want the whole of the framework.
You could summarize the above as "there is built-in a command class in WPF, but it's not really useful in the context of MVVM".

Are there any performance implications with CanExecuteCommand?

What are the performance implications of using the CanExecuteCommand of the ICommand object. Is the method executed over and over again?
I need to iterate through a collection of about 200 objects based on which its decided whether the button bound to the Command should be enabled? Does the CanExecuteCommand get executed repeatedly which will make my application slow
The ICommand interface is the following:
public interface ICommand
{
// two methods
bool CanExecute(object parameter);
void Execute(object parameter);
// one event
event EventHandler CanExecuteChanged;
}
The CanExecuteChanged event should be raised any time you want to indicate that the CanExecute method should be checked/called by WPF. Whoever implements ICommand should raise the event and whoever needs to refresh the button enabled state on the GUI (the WPF system) should register for and handle the event and it calls CanExecute.
In Josh Smith's RelayCommand class, he uses WPF's built-in CommandManager class to raise CanExecuteChanged:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
In essence, WPF's CommandManager is a singleton that listening for all sorts of routed events: KeyUpEvent, MouseUpEvent, etc... and then tells everyone "hey something interesting happened" by raising its RequerySuggested event. So if you are using RelayCommand, your CanExecute will get called every time CommandManager thinks something interesting happened on the GUI (even if it has nothing to do with your collection). If you have 50 commands, each time you key up, it's rechecking all 50 commands. So yes, this could be a performance issue. However, if your logic in your CanExecute method is really simple, it's probably a non issue. Takeaway point: don't make database or network API calls in the CanExecute method.
The alternative to piggybacking off CommandManager.RequerySuggested to raise the ICommand.CanExecuteChanged event is to roll-your-own version of RelayCommand where you do your own checking and raise CanExecuteChanged manually, or look at the Prism framework's DelegateCommand class, where they do not tie into CommandManager and you have to manually raise the CanExecuteChanged event, which you could probably do by creating a listener for PropertyChanged and then raising CanExecuteChanged on the command.
I agree with #Will above though. RelayCommand will probably work over 80% of the time without issues. If you do start finding performance issues, then you can create your own version of RelayCommand or use the Prism DelegateCommand and raise CanExecuteChanged manually.
For future googlers:
I have created a somewhat different command implementation. For one, it is bound to the OnPropertyChanged event of the ViewModelBase class, but it also allows the View Model to Raise the CanExecuteChanged event for all Command instances within it, regardless of a change in property, such as in the case of a One Way To Source binding scenario.
this solution is a part of the PerrypheralFrameowrk.WPF Assembly, available on nuget and codeplex. Look it up. The codeplex wiki has a detailed documentation, and so do the classes in the assembly.

Is EventToCommand passing EventArgs bad practice?

I've recently been using the MVVM light toolkit for Silverlight 4.
I really like the EventToCommand behaviour that is included, it makes life a lot easier. One thing I've been wondering about is if setting PassEventArgsToCommand="True" is bad practice as it will tie a particular RelayCommand to a particular event in the View.
E.g. If my RelayCommand is defined as:
public RelayCommand<System.Windows.Input.KeyEventArgs> myCommand
Then this can only be called by a KeyUp, KeyDown etc event.
I thought the ViewModel was to have no UI knowledge (e.g. expose a boolean converter and use a converter to change that to a Visibility), doesn't PassEventArgsToCommand break this?
The ViewModel is the model for the view so where you are referring to state that the view must have or data it should represent then the ViewModel should handle it.
It could be reasonable to use the Visibility enumeration to represent what part of the view should be viewed as that is about the state of the view.
As for the KeyEventArgs, this has come from an action from the user and represents some state of the command which if you need to know what key was pressed then it is a reasonable expectation of the ViewModel to handle.
If you introduce more abstractions and complexities to remove this event arg then you might have future maintenance issues provided you can unit test it with this command.
The only time I would not use Visibility or KeyEventArgs or the like would be if I wanted to use the same ViewModel for other UI technologies. If this is your case then I would create the abstraction (although in my experience this is rare and would typically involve their own ViewModels anyway).
It might not be a good idea to pass the KeyEventArgs directly to your ViewModel if you want to unit test the ViewModel - i.e. you want to invoke a command that takes KeyEventArgs as a parameter.
The reason for this is that you can't instantiate KeyEventArgs in Silverlight (at least not as far as I could see) because KeyEventArgs has no public constructor in Silverlight.
This means you can't pass a key from your unit test. In this situation it may be better to map the specific key(s) to the command in your view / XAML rather than just using an EventTrigger for the KeyDown event.
See this as one solution - this provides a KeyEventToCommand class that allows you to map the keys to commands directly in the XAML.
http://mvvmlight.codeplex.com/discussions/252898
One way to decouple the ViewModel from the View is to use a "broker" - something that mediates the communication between the two. I have used MVVMLight's Messenger class to implement a message broker with good results.
HTH, indyfromoz

ICommand vs RoutedCommand

Let's have a button Command property bound to a custom command.
When should I implement ICommand and when derive from RoutedCommand? I see that RoutedCommand implements ICommand.
In which case could I need to implement an ICommand?
What about MVVM model? Which one suits better for this purpose?
As you have noticed the RoutedCommand class is an implementation of the ICommand interface, its main distinction if that its function is similar to that of a RoutedEvent:
The Execute and CanExecute methods on a RoutedCommand do not contain the application logic for the command as is the case with a typical ICommand, but rather, these methods raise events that traverse the element tree looking for an object with a CommandBinding. The event handlers attached to the CommandBinding contain the command logic.
The Execute method raises the PreviewExecuted and Executed events. The CanExecute method raises the PreviewCanExecute and CanExecute events.
In a case when you don't want the behavior of the RoutedCommand you'll be looking at your own implementation of ICommand. As for the MVVM pattern I can't say that one solution, it seems that everyone has their own methodology. However, here are a few approaches to this problem that I've come across:
Using RoutedCommands with a ViewModel in WPF
Relaying Command Logic
Simple Command (almost identical to Relay Command but worth reading)
The only thing I would add to Rich McGuire's answer is that RoutedCommands (and their more prevalent descendant RoutedUICommand have to be wired up with event handlers to work correctly.
Most MVVM implementations I have come across attempt to leverage binding against the ViewModel and thus the ViewModel (and not the View) owns the CanExecute/Execute logic.
In contrast, the event handlers move that burden to the View. The handling can then be propagated to the ViewModel, but this means a slightly higher degree of coupling between ViewModel and View (casting + method call, etc.).

MVVM ICommand alternative

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
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.
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).
ICommand gives you CanExecute, which is needed for control enabling. A simple delegate does not. ICommand is the way to go.
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.
Due to the way in which the title of this question is worded, readers might arrive here looking for an alternative to ICommand, instead of just a way to bind a UI action directly to a method of a viewModel. (Which is of little value, since it leaves open the question of what to do with the 'CanExecute` part.)
The use of ICommand is problematic in and of itself because it is defined in Windows.Input, which means that in order to declare ICommands in your ViewModels you have to reference WPF and the kitchen sink from within your application logic, and once you have done that, any noob might notice that MessageBox and a vast array of other GUI functionality is available, and might start making use of it, resulting in a terrible mess of mixed application logic and presentation logic.
So, if you want to get rid of using System.Windows, then you need to get rid of ICommand, and if you want to get rid of ICommand, then you might be happy to know the following:
WPF (specifically, the XAML designer) does not require your viewModels to statically expose instances of the ICommand interface.
By statically here I mean that the designer does not need to be able to prove, during design time, using reflection, that your command objects implement the ICommand interface; instead, WPF checks at runtime to make sure that UI actions are bound to objects which do in fact turn out to implement ICommand.
So, in your viewModels (application logic) instead of the ICommand interface of WPF you can be using some Command interface of your own device, and all you need to ensure is that the class that you will be instantiating at runtime to implement your Command interface also implements ICommand to keep WPF happy. This way you can avoid including ICommand from within your ViewModels, and subsequently you might be able to avoid having to reference System.Windows in your application logic.

Resources