39
votes

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.

7
What makes you think a ViewModel cannot be bound to different sources of data?Akku
The View only consists on one Model via Dependency Injection. So the constructor takes in only one Model.Carven
Please reread my comment: What makes you think that the ViewModel (not the view) cannot be bound to different other models (not ViewModels)Akku
Yes, I was referring to the ViewModel, not View. Typo mistake. Sorry about it.Carven
ViewModel is a Model of View, so it is related directly only to View. Do not try to follow the rules, there are no strict rules in patterns and practices.Alex Burtsev

7 Answers

47
votes

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
  }
}
14
votes

You can use multiple models in a view model. The purpose of the view model is to abstract away the business / data layer (i.e. the model).

However, using more than one model usually indicates that the view is too large. You might want to split it into user controls (which have their own view models).

4
votes

a viewmodel contains the "view logic" - so all you wanna show on the view is exposed through the viewmodel. if you wanna show data from diffenrent "models" then your viewmodel agregate this and the view can bind to.

the main purpose from mvvm was btw unit test. this mean easy testing of view logic without UI.

EDIT: why do you think:

ViewModel only has one single parameter for the View in its constructor

EDIT2:

there btw two main approaches to work with mvvm, first is "View First" second is "Viewmodel First" you can of course mix up both and choose the best approach for you needs.

2
votes

A ViewModel may and in many cases does use multiple Models. It is itself a "Model" of your view.

Consider a profile screen that a user enters their personal information including address. If the address is stored in an "addresses" table and the rest in a "profile" table, then the ViewModel uses both the Profile and Address models to create a unified ViewModel.

As jgauffin mentioned in his answer, many times you can use user controls to achieve a one to one relationship, but you can also introduce needless complexity by trying for this 100% of the time.

2
votes

I would make sure you understand the difference between view, viewmodel, and all other model classes. The ViewModel is the model object that is filled with data that the view can be bound to. It just exists to provide data to the view, which makes the ViewModel object unit-testable, and the whole business logic separate from the view. So, you can develop your business logic entirely without using the view itself, and can replace the view with just building or using another view and binding to the ViewModel object's properties. If a view is full of empty text fields for example, the contents of the text fields can be bound to different properties of the view model.

There usually really should only be one view model. BUT if it's too complex, you can use subproperties of the bound objects like described in Binding to ViewModel.SubClass.Property (sub-property)

The ViewModel can get the data it returns to the view from a lot of different sources, business objects, databases, whatever.

1
votes

Usually there is one ViewModel per Model. These ViewModels contain the logic to handle the model's data. On the other side every view has it's own view model, too. So this means:

class ModelA 
{
    bool TestValue{get;set;}
}
class ViewModelA<ModelA>
{
    ValueViewModel<bool> TestValue{get; private set;}

    public ViewModelA(ModelA model) 
    {
        base.Model = model;
        this.Initialize();
    }
}

class ModelB 
{
    string Username;
}
class ViewModelB<ModelB>
{
    ValueViewModel<string> Username{get; private set;}

    public ViewModelB(ModelB model) 
    {
        base.Model = model;
        this.Initialize();
    }
}

These are the ViewModels that encapsulate the models. The views have their own ViewModels:

public ViewModelForExactlyOneView
{
    public ViewModelA{get;set;}
    public ViewModelB{get;set;}
}

To answer your question, ViewModel1 refers to ViewModelA and ViewModelB. The View therefore can get it's data from ViewModel1.ViewModelA.TestValue.

-4
votes

just use the User model in your view

public partial class User : Login
{
    public string Password { get; set; }

    public List<Customer> customer { get; set; }
}

in this the another model login inherited and the customer model also used in this model..