I want to find out the event handling scheme using the MVVM pattern.

  1. As I understand it, there should be no event handler in the code, since they are possible only in the code behind, and it is bad to use it, right?
  2. All event processing takes place through commands. To do this, you need to write a simple class like this, in which to insert your delegates, create command properties and bind them to elements?

    class RelayCommand : ICommand { private Action<object> _executeDelegate; public RelayCommand(Action<object> executeDelegate) { _executeDelegate = executeDelegate; } public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { _executeDelegate(parameter); } } 
  3. And how to handle different events from the same element? As I understand it, the command is executed for a single "main" event?

  4. Is it possible to get event arguments (the same arguments as a regular handler)?
  5. Are there any more beautiful methods? For example, through command binding? Just how do these bindings add to the window if the ViewModel does not have a link to it?

    2 answers 2

    1, 2. For my taste, not quite.

    The correct place for event handlers is UI-specific tasks. For example, you want to measure some kind of control, and if its width is less than 10% of the container, then hide it completely. To do this, you subscribe to a resize event. This is a specific presentation-level task that has nothing to do with VM. To use a command for her is wrong, you don’t need a weak connection here.

    3. Usually the element should not have two commands in its interface. For example, for a button, the only event that may be of interest to the VM level is pressing the button itself. Resizing the button for the VM is of no interest. Accordingly, the button has only one command.

    If you are writing a custom control that can actually produce several different interesting for VM-level events, define several commands in it.

    4. I can not add anything to the point of view @ixSci: there is a CommandParameter for this.

    5. It is possible to further reduce connectivity by using predefined commands. Example: a menu item can declare a predefined ApplicationCommands.Save command ( <MenuItem Header="Сохранить" Command="Save" ... /> ) as its command, and bind the implementation of the Save command somewhere else in the code (see CommandBinding ) .

    • Yes, for example, you need to subscribe to the event CommandBinding.Executed from the code behind? VM which is not code behind View has no idea, right? - RussCoder
    • @RussCoder: I did it differently: VM created CommandBinding 'and passed them to MainVM , and the application performed foreach (var binding in mainVM.GlobalBindings) CommandManager.RegisterClassCommandBinding(typeof(Window), binding); during initialization foreach (var binding in mainVM.GlobalBindings) CommandManager.RegisterClassCommandBinding(typeof(Window), binding); . There is no need to subscribe to the code-behind. - VladD
    • one
      @RussCoder: But the simplest scenario, of course, is to expose a command as a VM property. - VladD
    1. This is true, but any maxim is nonsense. Therefore, we must look at the circumstances. In any case, this is what you want to strive for.
    2. Yes, or use ready-made MVVM libraries, such as MVVM Light.
    3. In MVVM Light, which I already mentioned, there is such a thing as EventToCommand , you can see an example here.
    4. The command has a CommandParameter , where you can send anything you want: <Button Command="{Binding SomeCommand}" CommandParameter="{Binding}"/>