This project is read-only.

about "update" in MVVM

Dec 7, 2009 at 4:28 PM

Hello,

First of all, I would like to thank you for your work. It's a great source of inspiration for my WPF & Silverlght application.

I have a question about the "update" phase.

You replaced "ViewModelBase" with "ObservableObject" for the INotifyPropertyChanged base class implementation.

The consequence is that a class of the Model can inherit from this class and notify the observers after an update (a ViewModel -or a View if it directly binds it-).

But the other consequence is : whenever the repository has succeeded or not in saving the changes, each viewmodel or view that binds this object reflects the changes automatically.

If we take your sample application with the Customers. Suppose that we have a form to create or modify Customer informations.

We have a CustomerViewModel for this form. But we can have in our application several CustomerViewModel instances of the same customer, typically in a datagrid containing the Customers and their main properties.

We don't want that the datagrid reflects the changes until the Customer has been saved (and commited) in the repository.

My idea is to add a "CustomerUpdated" event in the CustomerRepository class that is raised after SaveChanges.

Therefore, every CustomerViewModel related to this Costumer can call NotifyPropertyRaised on all the Customer properties.

What do you think about it ?

Does anyone have ever faced this situation? How did you solve it ?

Regards,

 

Littlesteps

Dec 7, 2009 at 4:43 PM

If you have multiple VMs associated with the same Model object, but do not want to have them all keep in sync with the Model object's state at the same points in time, then you will have to take a different approach.  There are several options:

1) On the VM whose properties should not immediately update when a property on the Model changes, set the Bindings' UpdateSourceTrigger to 'Explicit' and then call UpdateSource() on each BindingExpression when you want the values to be transfered to the VM (i.e. after a Save operation).

OR

2) Externalize the editable state of the Model to a separate class and expose two instances of that class off the Model.  One instance represents the "edit" values, and the other instance represents the "saved" values.  The editable VMs would bind to the "edit" instance's properties, and the read-only VM would bind to the "saved" values.  When you call Save on the Model, you would update the "saved" instance to contain the "edit" instance's values.

OR

3) Maintain two repositories of Model objects: the "edit" collection and the "saved" collection.  Each VM would only bind to objects from one of the collections.  When you save an object in the "edit" collection, you would reflect those changes in the "saved" collection.

Josh

Dec 7, 2009 at 11:14 PM

Hello Josh,

Thanks a lot for your answer.

I know and often use the option 1: "UpdateSourceTrigger set to Explicit".
It is obvious for simple data types (e.g. string values), but I don't know if it's possible to use it for a parent/child relationship.
For instance, suppose that I have an order with a list of OrderItems. When the user edits the Order, he can add or remove OrderItems. A typical implementation is: A listbox binds an ObservableCollection (or a CollectionViewSource) and each new item in the list corresponds to a new OrderItem object in the model... Is it possible to use UpdateSourceTrigger in this case?

I'm not really convinced by your option 2, because I'm not sure that a model object has to know that is has been saved in the repository.
I never call Load or Save on a Model class. The viewmodel has the responsability to load from and save to the repository the model, as you did in your Customer sample application.
Am I right?

I think that your Option 3 is probably the best for me. I will think about it.
Thanks again.


Best regards,

Littlesteps

Mar 4, 2010 at 1:39 AM

Hello,

you are saying that it is possible to use UpdateSourceTrigger = Explicit in MVVM, I don't understand how instance of BindingExpression could be got in ViewModel if ViewModel doesn't have a reference to UI components. So, if I didn't use MVVM then in code behind file I would use something like that:

        BindingExpression be = tbAge.GetBindingExpression(TextBox.TextProperty);
        be.UpdateSource();

 

where tbAge is my TextBox which is bound in XAML, but how to get instance of BindingExpression in MVVM case ?

Aug 12, 2011 at 7:32 PM

Josh,

Do you have an example of using UpdateSourceTrigger=Explicit that adheres to MVVM?  It seems like a common scenario would be:

  • 1. In one View (UserControl), a ListView that displays an ObservableCollection of [Customers].
  • 2. In another View (UserControl), many TextBoxes, ComboBoxes, CheckBoxes, etc. that will display data for the specific [Customer] that is selected in the ListView.  This view would have a Save button that uses a Command to update the repository and notify the ListView to update itself.

I was considering creating a copy (deep copy with new reference) of the SelectedItem [Customer] from the ListView and passing the copied data to the details view.  The details view binds to the copied data.  When the Save button is pressed, the values for the original SelectedItem are updated with the values in the copied data.  Does this sound reasonable?