Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stale data in MVVM ViewModels with dependency injection

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:

  1. The data in the Views is never updated, not even when closing and re-opening them, because the ViewModel instance is always the same.
  2. 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:

  1. 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.
  2. 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?

like image 713
Daniel Hilgarth Avatar asked Nov 05 '22 05:11

Daniel Hilgarth


1 Answers

Implement the ViewModelLocator in such a way that it creates the requested ViewModel each time the corresponding property on the ViewModelLocator is called.

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.

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.

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.

like image 176
Reed Copsey Avatar answered Nov 09 '22 16:11

Reed Copsey