A very common implementation of RelayCommand
seems to include the following lines:
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
This seems very flawed to me, because CommandManager
is a WPF component and usually my commands are located in a viewmodel class. Since the viewmodel is not supposed to know the view and should work with different frameworks and such, this seems very strange to me. For example this implementation will not even be possible if you separate your viewmodel in an extra project, that doesn't know the WPF namespace (e.g. PCL).
Is this implementation violating the MVVM pattern?
Or do you maybe place the RelayCommand
in your view somehow?
If this is indeed flawed, is there a best practice implementation that solves this issue?
The RelayCommand and RelayCommand<T> are ICommand implementations that can expose a method or delegate to the view. These types act as a way to bind commands between the viewmodel and UI elements.
Commands are an implementation of the ICommand interface that is part of the . NET Framework. This interface is used a lot in MVVM applications, but it is useful not only in XAML-based apps. The ICommand interface specifies three members: The method Execute(object) is called when the command is actuated.
The ICommand interface is the code contract for commands that are written in . NET for Windows Runtime apps. These commands provide the commanding behavior for UI elements such as a Windows Runtime XAML Button and in particular an AppBarButton .
This is an easy and quick & dirty implementation mostly only used for tutorial cases that do not tie the tutorial to a specific MVVM framework, but act as a generic do-it-yourself MVVM tutorial.
This approach - other than tight coupling - has several other disadvantages.
When the CommandManager.InvalidateRequerySuggested()
method is called, the CanExecute
method of every command will be called. If you have 100s of commands in your Application, this can have severe impact on performance of your WPF Application.
I personally always suggest using a matured MVVM Framework (Prism being my favorite for LoB applications). There the commands usually don't implement it this way but you call MyCommand.OnCanExecuteChanged()
(in case of Prism) to trigger CanExecute
validation for one single command.
If you have compound or multiple commands that depend on each other, you tie it yourself in code, i.e. by storing a list of related commands inside the view they are used and loop through it or registering their OnCanExecuteChanged()
methods to a multicast delegate and calling that instead.
Is this implementation violating the MVVM pattern?
Technically yes.
Or do you maybe place the RelayCommand in your view somehow?
Not really, though you may be able to abstract it with an external factory, it do not seems to make sense (see the issue above)
If this is indeed flawed, is there a best practice implementation that solves this issue?
Don't have a global invalidation of commands state anyway. Tie the commands yourself that need their execution state tied together.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With