In my WPF application I use the MVVM pattern together with dependency injection.
The ViewModels that prepare data from the database get the repository injected into the constructor. They also populate the properties with the data from the repository in the constructor.
The ViewModels are all created in the static constructor of the ViewModelLocator class that all Views use to bind to their ViewModel.
This has the following disadvantages:
- The data in the Views is never updated, not even when closing and re-opening them, because the ViewModel instance is always the same.
- Upon opening the first view, all ViewModels are instantiated and the data they require loaded from the database.
I can think of two ways to solve these problems:
- Make every ViewModel implement a method that reads the data from the database and initializes the properties – instead of doing so in the constructor. This would require calling that method every time a view is opened. This introduces temporal coupling which I don’t like.
- Implement the ViewModelLocator in such a way that it creates the requested ViewModel each time the corresponding property on the ViewModelLocator is called. I don’t like this method, because my composition root wouldn’t be executed at the start up of the program but would be spread throughout the life time of the program instance.
Is there another way to solve this problem? How are others solving this?
This is more of the approach that I typically take in situations like this. However, instead of having the ViewModelLocator composed via DI of ViewModels, I compose factories that create the ViewModel.
This gets “solved”, at least partially, by having the composition compose factories instead of the types themselves. The composition happens once at startup, but creation can occur at any time of the ViewModel in question.
For example, using MEF, you can switch your imports around to use
ExportFactory<T>instead of their type directly. Along with a NonShared Creation Policy, you can construct ViewModels, as needed, and always work with fresh data, without the temporal coupling problems.