MVVM – State of Selected Items in View or ViewModel?

mvvm

Myself and my colleague were having a discussion about MVVM and how lists and selected items should be stored in view / viewmodel.

I think the viewmodel should only offer up the data and allow the view to interpret it how it likes. It could display it as a list with a selected item or it could show it completely differently.

Therefore I think the viewmodel should look like this:

public class MajorVM
{
    ObservableCollection<MinorVM> List
}

And the view like this:

<Grid>
    <Listbox Key=ListBox Items=Binding DataContext.List />
    <ContentControl Content=Binding ListBox.SelectedItem />
</Grid>

My colleague thinks that I'm changing between data contexts making the view code harder to follow.

My colleague believes the viewmodel should contain the state of the view and that this will allow easier manipulation of the view in future. E.g. controlling selection via the viewmodel.

Therefore it would look like:

public class MajorVM
{
    ObservableCollection<MinorVM> List
    MinorVM SelectedItem
}

With a view that looks like this:

<Grid>
    <Listbox Items=Binding DataContext.List />
    <ContentControl Content=Binding DataContext.SelectedItem />
</Grid>

To me this doesn't seem correct because the viewmodel now has a SelectedItem property on it that isn't mentioned anywhere other than the view. It's a view implementation on the viewmodel.

Best Answer

Its generally better to bind controls in the View to Properties of the ViewModel rather than other aspects of the View.

There is one clear benefit to the ViewModel having SelectedItem in this case, which is that without it no item is initially selected when the view is displayed.

It's hard to put a line in the sand that demarks 'this functionality is ok to add to a control' and 'this functionality should be put in the viewmodel' though.

Effectively here you are simply making a compound control with a selection and detail view. There's nothing which makes that quantitatively different from, say a ComboBox/DropDown control.

But if we do want to add some custom logic, say we want to select extra info from the database for the selected item. Having the selected item and an ItemSelected command on the ViewModel will make this much easier.

With WPF you have a number of options when it comes to adding custom logic.

  • Code Behind page. You can handle events and directly manipulate controls
  • Custom Controls. You can override the behaviours of a control, changing its logic.
  • Behaviours. You can add extra behaviour which can be linked to a control in the view
  • Binding - to VM. You can bind controls to properties of its data context
  • Binding - to View. You can bind to properties of other Controls
  • Styles - You can use styles and data triggers to change the properties of Controls
  • Data Templates. You can customise a control with a Data Template
  • Content Templates. You can change the way a control presents itself
  • Custom Converters. You can put logic in converters to change the way a binding works eg EnumToBrush

You are overloaded with options and they all work in different ways. But if you are doing MVVM try to favour Binding to VM and Behaviours

Related Topic