views:

91

answers:

3

OK, let's say I am creating a program that will list users contacts in a ListBox on the left side of the screen. When a user clicks on the contact, a bunch of messages or whatever appears in the main part of the window.

Now my question is: how should the MVVM triads look? I have two models: Contact, and Message. The Contact model contains a list of Message models.

Each ViewModel object will contain a single corresponding Model, right?

And what about the Views? I have a "MainView" that is the main window, that will have things like the menu, toolbar etc. Do I put the ListBox in the MainView? My confusion is with what to put where; for example, what should the ContactView contain? Just a single instance of a contact? So the DataTemplate, ControlTemplate, context menus, styles etc for that single contact, and then just have a ListBox of them in the MainView...?

Thanks.

A: 

Each ViewModel object will contain a single corresponding Model, right?

No, if you view contains say a list of contacts and an active contact that has a list of messages you view model could contain a collection of contact model objects and an active contact view model. The later could contain a collection of message model objects for that contact.

I your view you could bind the list box to MainViewModel.Contacts and the selected item in the list box to MainViewModel.SelectedContact. The list of messages could then be bound to MainViewModel.SelectedContact.Messages.

Martin Liversage
So: MainViewModel has a list of all ContactViewModels and a single active ContactViewModel. And then the ContactViewModel contains a list of MessageModels? How am I going to fit the MessageViewModel into all this?
Harry
You only need a `MessageViewModel` if you have a separate view of a message. That could either be an embedded control or a separate view like a dialog box. In general you have one view model for each view.
Martin Liversage
A: 

I think there is no clear definitions with ViewModels just yet, but this is how I see it...

Viewmodels shouldn't have "child" Viewmodels, these are not data relationships and hierarchies. A Viewmodel represents a single view, and contains the model/data for that view. In Contrast a View is composed of user controls and each of those controls could have their own Viewmodel, the the DataContext remains the same as the parent view.

In other words, the hierarchy is visual, not data driven.

Doobi
+1  A: 

The heart of MVVM pattern is the Model which is the structure of your data. So you have the Contact Model and the Message Model which are related and is well set. Now you want to design your interface. The UI contains a single window(the MainView). So you would need a single ViewModel. So what does the ViewModel consist of?

Let us assume that you want to display only a single contact in your MainView and not a collection. Now your MainViewModel can just have references to your Contact's properties which are to be exposed into the view.

Contact c = /*Retrieve a contact from db*/;

ContactName = c.Name;  //Create these two properties
ContactPhone = c.Phone; //Assuming only these two properties are required by your view

Now you can bind these properties to your MainView like this

<Textbox Text={Binding ContactName} /> <!-- Assuming the DataContext is assigned -->
<Textbox Text={Binding ContactPhone} />

But we have to display a collection in our MainView. Hence we define the individual listitem as a new view. We also need a list of ContactName and ContactPhone. Hence we wrap these two properties into a class and make a list of it. This Class is termed as ViewModel.

(Here you have to add Messages Property also)

Hence the individual views have their own viewmodel. Now we integrate these views into our MainView.

Now what should the MainViewModel contain?

  • List of ContactViewModels - ContactList
  • Selected ContactViewModel - SelectedContact
  • List of MessageViewModels - SelectedContactMessageList

How are these wired up?

  • ContactList - bound to Contact ListView
  • SelectedContactMessageList - bound to Message ListView
  • SelectedContact - bound to Contact ListView's SelectedItem. The setter should modify the SelectedContactMessageList according to the Selection like this
SelectedContactMessageList.Clear();
foreach (Message message in SelectedContact.Messages)
{
    SelectedContactMessageList.Add(new MessageViewModel(message))
}// converting the resulting models from SelectedContact.Messages to viewmodels

That's it. This is how I've understood MVVM.

And about the point,

Each ViewModel object will contain a single corresponding Model, right?

No! Instead each View is mapped to a single ViewModel

Create a ViewModel for each View in your application and have only those properties that are required by your View, in your ViewModel.

Veer
And what about if I want to edit the data? Or save the data back to the database/hard drive?
Harry
Whenever you edit the data in view, as it is bound to the viewmodel, it propagates the changes to the model automatically. Hence you can just save the corresponding Model to your database. Do you use Linq to Sql by the way?
Veer