Nir Smadar
Nir Smadar

Reputation: 457

Who should call the VIewModel in WPF/MVVM the logical unit or the view?

My question is of "What is the best practice?" type, in a very specific case:

I have a View that contains a listbox of checkboxes.

The listbox.ItemsSource is bound to a collection in the ViewModel (List of Person). And each checkbox.IsChecked is bound to Person.IsSelected.

The check/uncheck of a checkbox activates a 'Refresh' method in the ViewModel, that may or may not re-set the Person.IsChecked of all Persons. That, of course, should notify the UI that Person.IsChecked (might have) has changed.

My question is: Who should be responsible of calling ViewMode.Refresh? Should the UI call the method through an event or Command maybe? Or should the ViewModel subscribe to a proper event in Person.

Upvotes: 1

Views: 498

Answers (4)

nmclean
nmclean

Reputation: 7724

I think you have to ask yourself, what is the "refresh" in response to?

If it's in response to the check box physically being clicked, then it's the view's responsibility to call it.

If it's in response to the person being selected, the viewmodel should be watching its own collection for changes to IsSelected.

I agree with MehaJain that the latter is harder to set up, but the alternative breaks up the responsibility of a single unit of work between the layers, meaning that the logic will need to be duplicated in any other function that causes IsSelected to be changed. This includes other views binding to the same information, other commands (say you have a button for running a filter that selects certain people), and tests.

Upvotes: 1

WiiMaxx
WiiMaxx

Reputation: 5420

depending on what you mean by "call"

here are the answers

if you mean create:

  • other ViewModel
  • anything that's not a View or an Model(because non of them should know your VM)

if you talking about executing a Method:

  • self execute (e.g. after PropertyChanged, Command, ...)
  • other ViewModel
  • anything that's not a View or an Model(because non of them should know your VM)

also important in your case:

you say your list is bounded to Collection
and here you could get some trouble because your View changed the Person.IsSelected which should raise a PropertyChanged for your IsSelected.
Now it will stuck because ObservableCollection doesn't get notified if your Item Property Changed that is a known issue. To fix this problem you need to wire up your INotifyPropertyChanged event to the CollectionChanged event from your ObservableCollection. So it can bubble up to your VM and it can execute his Refresh()

Here you can see an example how you could do it.

Upvotes: 1

MehaJain
MehaJain

Reputation: 55

I would prefer to Refresh the View Model through the event or Command.

Because subscribing the collection members is tricky. Let say you want to use the second approach: Subscribing to the Person class changed event. Then it can have following disadvantages:

  • In the constructor of your view model you have to subscribe each "Person" member of your list.
  • In view model whenever collection gets modified then you have to subscribe/unsubscribe the added/deleted members of that list.
  • While disposing your view model, you have to unsubscribe the subscribed changed events.

So, this is an over head if you go for subscribing the change event of Person class.

Upvotes: 0

Kent Boogaart
Kent Boogaart

Reputation: 178650

If the UI is bound to IsChecked, nothing needs to notify it. Or, rather, WPF itself notifies it. That is one of the attractive qualities of MVVM. The view model can simply update its state according to its own set of rules, and the view automatically receives those changes via bindings.

Upvotes: 3

Related Questions