0

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.

  • In your viewModel example (the one containing just an observable collection), how does the ViewModel know which item has been selected? – Robert Harvey Aug 6 '18 at 16:24
  • It doesn't. The viewmodel doesn't do anything with the selected item. It's only for determining which content is shown in the ContentControl. – user3161729 Aug 6 '18 at 20:52
3

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

  • Do you have any links regarding your very first comment? I've tried looking on google and I'm not really finding anything on the subject. – user3161729 Aug 6 '18 at 14:51
  • no. but as an authority on the subject you can trust that i am correct – Ewan Aug 6 '18 at 14:52
  • I don't doubt your credentials and I understand that to you this might be a simple question with a simple answer but I think it would be poor form for me to accept this answer on that basis alone. Your only argument is essentially the first line without anything backing it up. – user3161729 Aug 6 '18 at 15:03
  • what about paragraph 4? – Ewan Aug 6 '18 at 15:03
  • 1
    I've always been under the opinion (perhaps illusion) that the viewmodel and view should be fiercely independent. To me changing your viewmodel to suit the view is akin to adding properties to it so it can be unit tested more easily. – user3161729 Aug 6 '18 at 15:15
2

Typically, a SelectedItem target binding belongs on the ViewModel.

This is because you usually want to do something with the SelectedItem (edit, delete, etc).

Having the SelectedItem on the VM also allows you to change the SelectedItem from VM code in reaction to other events in the system.

Now, if this specific SelectedItem is only for viewing purposes then you could make the case that it only belongs in the view. However, I find this to be an unusual approach for the MVVM pattern and I can see where it could be considered confusing.

2

The viewmodel doesn't do anything with the selected item. It's only for determining which content is shown in the ContentControl.

Then you don't need a SelectedItem property in the ViewModel. Simple as that.

However, that means that you must now take responsibility for updating the ContentControl in the View yourself using code behind, whereas if you'd exposed a SelectedItem on the ViewModel instead, you could have simply used Linq and data binding to accomplish the same thing in the ViewModel.

Technically, what data you decide to display in your ContentControl is a business rule, not a UI function. If you can implement such business rules in the ViewModel, it is better from a maintenance perspective, since the View doesn't have to care about the data mechanics.

  • "However, that means that you must now take responsibility for updating the ContentControl in the View yourself using code behind" Assuming that the ContentControl simply isn't just showing the data; its possible there is nothing to be done in the ContentControl that can't be accomplished with bindings. – Andy Aug 6 '18 at 23:05
  • yeah in the example the contentcontrol is bound directly. – Ewan Aug 7 '18 at 6:48

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.