13
votes

How do I share data between multiple ViewModels ?

For example there is a class named Project in application .

    public class Project : ModelBase
{
    private string _projectName;

    public string ProjectName
    {
        get { return _projectName; }
        set
        {
            _projectName = value;
            RaisePropertyChanged(() => ProjectName);
        }
    }
}

In multiple ViewModels application should access ActiveProject.
What's the best way to share Project between ViewModels ?

  • Mediator Pattern ? (Messaging)
  • Static object
  • Singleton pattern (If yes how?)

I've used Messaging before but it needs much codding . For all ViewModels I've to create ActiveProject property and also have to register a messenger to update that.


I use MVVM Light framework.
Any code example would be appreciated.

5
Is your ActiveProject created somewhere by one of the view models? If so, messaging would probably be the best (and it's not that verbose). Other option is to inject an ActiveProject to every view model that needs it while setting the ActiveProject lifetime to singleton in the IoC container of choice - third option you've suggested... But so far it's mostly guessing on my part.Patryk Ćwiek
@TrustMe-I'maDoctor Why do we WPFers always overcomplicate everything? Wouldn't it be much easier to store that in the App class as a static property?Federico Berasategui
@HighCore That's always an option... A static read-write property rubs me in a wrong way though, too easy to abuse. :)Patryk Ćwiek
@Trustme-I'maDoctor Using DI techniques would be great. please give me an example or sample link related to my problem.Unforgiven
@Unforgiven e.g. SimpleInjector automatically resolves the concrete types, but you can do container.RegisterSingle<Project>(() => new Project()); and then just request a Project activeProject in the constructor. Other IoC containers also support named injection, so you can use that too.Patryk Ćwiek

5 Answers

7
votes

I would create a ViewModel that acts as a parent to all the Project ViewModels. (Let's call it Solution)

The Solution ViewModel would have the property ActiveProject and an observable collection of Projects.

6
votes

I would recommend the Mediator Pattern. I have used an EventAggregator for this type of messaging between VM's before and there is really not much to it.

3
votes

Don't, don't. Don't use singletons this way in your MVVM application. In fact, the Project class should be a model for your ViewModels. Just pass it in vm's constructor. If you really need to share one instance of Project class in multiple vm's, then use factories and some type of cache when constructing view models. If your vm reguires some more information, just create special Model class which will derive from Project (or implement IProject), so you can easilly use interface segregation principle.

1
votes

Singleton will definitely help. To implement, if I had a class named User:

    private static User mInstance;

    private User () //constructor
    {
    }

    public static User Instance
    {
        get
        {
            if (mInstance == null)
                mInstance = new User();
            return mInstance;
        }
    }
1
votes

You could have a static collection which your view model populate before you navigate to the new view model. The target view model can then retrieve the data from within it's constructor.

For example ViewModel1 (VM1) will create a Project and populate it. VM1 will then put the Project into a shard, static, collection. VM1 will then navigate to another view model (VM2). In the constructor of VM2 you would go to the collection and retrieve the Project placed in there by VM1.

If you used a dictionary of key-value pairs it would also allow you to share other data between view models.