wpfmvvmmvvm-lightrelaycommandrouted-commands

Correct way to handle commands that rely on multiple view models


I'm relatively new to WPF and MVVM and i am trying to understand how to use commands correctly when they have dependencies in more than 1 view model.

A couple of examples:

Is there some generally accepted way to deal with this which i am missing?


Solution

  • In general your view model layer should have a 1:1 relationship with your view, there should be no good reason for a "Save" function to exist in a view model which is then called by another view model.

    What it sounds like you should be doing is putting that logic into a service i.e. something like this:

    public interface ISerializationService
    {
        void Save(SomeData data);
    }
    

    Then you need an implementation for this service that does the actual work:

    public class SerializationService : ISerializationService
    {
        void Save(SomeData data)
        {
            // actual save happens here
        }
    }
    

    Your view models should then contain properties that point to instances of these services:

    public class MyViewModel : ViewModelBase
    {
        [Inject]
        public ISerializationService SerializationService { get; set; }
    
        // called when the user clicks a button or something
        private void ButtonClickCommand()
        {
            this.SerializationService.Save(this.SomeData);
        }
    }
    

    The only question remaining is "What sets the value of SerializationService?", and for that you need a dependency injection framework. There are plenty out there, MVVMLight installs one itself, but Ninject is the de-facto standard. When implemented properly the injection framework will create all view models for you and then "inject" the dependencies, i.e. your SerializationService property, of type ISerializationService, will be initialized with an instance of your SerializationService class (which in a case like this will also be configured to be a singleton).

    Dependency Injection takes a bit of work to get your head around but once you start using it you'll never look back. It facilitates complete separation-of-concerns whilst alleviating the need to pass pointers to everything all up and down your architectural hierarchy.