Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the common implementation of RelayCommand violating the MVVM pattern?

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?

like image 505
Tim Pohlmann Avatar asked Mar 10 '16 08:03

Tim Pohlmann


People also ask

What is the use of RelayCommand in WPF?

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.

What is a command MVVM?

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.

What is ICommand C#?

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 .


1 Answers

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.

like image 115
Tseng Avatar answered Oct 16 '22 15:10

Tseng