Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In MVVM, is every ViewModel coupled to just one Model?

In an MVVM implementation, is every ViewModel coupled to just one Model?

I am trying to implement the MVVM pattern in a project but I found that sometimes, a View may need information from multiple Models.

For example, for a UserProfileView, its UserProfileViewModel may need information from UserAccountModel, UserProfileSettingsModel, UserPostsDataModel, etc.

However, in most articles I read about MVVM, the ViewModel only consists on one Model via Dependency Injection. So the constructor takes in only one Model.

How would the ViewModel work when it has to get information from multiple Models? Or would such a situation ever occur in MVVM?

PS: I am not using the Prism or Unity Framework. I am trying to implement similar patterns into a project that I am working on which doesn't use Prism or Unity. That's why I need to understand exactly how some of these things work.

like image 744
Carven Avatar asked Oct 26 '12 11:10

Carven


People also ask

Can a ViewModel have multiple models?

ViewModel is nothing but a single class that may have multiple models. It contains multiple models as a property. It should not contain any method. In the above example, we have the required View model with two properties.

Can ViewModels communicate with each other?

One way to have disconnected ViewModels communicate to each other is to use a publish / subscribe mechanism such as PRISMs EventAggregator. However, in a parent / child ViewModel relationship, I think it's fine for the parent to have direct knowledge and control over the child ViewModel.

Should each view have its own ViewModel?

Yup, each view should have its on ViewModel. I don't know WPF inside out, but generally the ViewModel mediates between a UI component and a business logic component. In other words: It's specific to a view/model pair - this is the only reason for this component to exist...

Can a ViewModel contain another ViewModel?

Having a master ViewModel with several child ViewModels is very handy if you have a complex UI. The main ViewModel may be responsible for handling the top level UI controls and for coordination of the child VMs, while other ViewModels are responsible for communication with the sub regions of your UI.


1 Answers

In my understanding of the MVVM pattern, the only practical requirement is that the View gets all its data from the properties of a ViewModel (probably through a binding mechanism). The ViewModel is a class that you craft specifically for that view, and takes on the responsability of populating itself as required. You could think of it like ActiveRecord for the view.

As such, it doesn't matter what you do inside the ViewModel to obtain the data that its properties should show. You could get it by querying some services, reading one or more business entity models, generating it on the spot, or all of the above. It's perfectly normal to need a combination of all these things to make a functional view.

As in any presentation pattern, the point is just to separate the process of showing some data on the screen, from the process of obtaining that data. That way you can test each part of the process separately.

Edit: Here's a small but hopefully complete example of the flow of dependencies.

// Model/service layer  public class MyModelA {   public string GetSomeData()   {     return "Some Data";   } }  public class MyModelB {   public string GetOtherData()   {     return "Other Data";   } }  // Presentation layer  public class MyViewModel {   readonly MyModelA modelA;   readonly MyModelB modelB;    public MyViewModel(MyModelA modelA, MyModelB modelB)   {     this.modelA = modelA;     this.modelB = modelB;   }    public string TextBox1Value { get; set; }     public string TextBox2Value { get; set; }    public void Load()   {     // These need not necessarily be populated this way.      // You could load an entity and have your properties read data directly from it.     this.TextBox1Value = modelA.GetSomeData();     this.TextBox2Value = modelB.GetOtherData();     // raise INotifyPropertyChanged events here   } }  public class MyView {   readonly MyViewModel vm;    public MyView(MyViewModel vm)   {     this.vm = vm;     // bind to vm here   } }  // Application layer  public class Program {   public void Run()   {     var mA = new MyModelA();     var mB = new MyModelB();     var vm = new MyViewModel(mA, mB);     var view = new MyView(vm);     vm.Load();     // show view here   } } 
like image 194
Alex J Avatar answered Oct 13 '22 20:10

Alex J