3

This is more of a conceptual question. If it helps, lets say it falls into the MVVM pattern. I've never seen this addressed in any of my research into WPF Binding.

If you have a window where you have elements connected to view-model through binding and the user updates the record, but before saving decides to cancel the update, what would you consider the best method of reversing the changes would be?

I can think of a couple of possibilities:

  1. Instead of allowing the user to update the main display, have a second window pop up for editing that is bound to a copy of the VM and upon "Save", writes that data into the original VM and then updates back to the model. Increases memory usage and complexity of the Save function.
  2. Make a "pristine" copy of the original VM object and, upon "Cancel", write that VM back over the original (at which time the copy can be deleted). Increases memory usage and complexity of the Cancel function.
  3. Create a copy of each of the elements within the VM that might change upon creation and upon "Cancel", write those values back over the changed ones. Increases the size and complexity of the VM.
  4. Upon executing "Cancel", the VM hits the data source and reloads the record. Causes network traffic and DB access traffic and possibly lag time for display updating back to original state. Also might cause problems if the VM was updated from another process and these "external" updates should not be deleted.

Can anyone think of a better solution to this problem, or know of some obscure functionality within WPF that handles this "automatically"?

Dimondwoof
  • 71
  • 2
  • 6
  • Does this answer your question? [How to cancel an edit to an object using MVVM?](https://stackoverflow.com/questions/1091036/how-to-cancel-an-edit-to-an-object-using-mvvm) – StayOnTarget May 04 '20 at 18:45

3 Answers3

4

I think the easiest way to do this is to use a BindingGroup, which will delay updates to the VM until the user explicitly commits the changes. This way, the controls will cache the changed values, and the BindingGroup will be able to restore the original values from the (still unchanged) VM.

hbarck
  • 2,934
  • 13
  • 16
  • Yep. This approach doesn't have drawbacks listed above. Unfortunately it might introduce problems with object validation because it's better to perform complicated validation inside Model or at least ViewModel – Ilya Serbis Nov 22 '12 at 21:57
  • 1
    Well, if a ViewModel can expose ICommand implementations, why shouldn't it expose ValidationRules? You could implement ValidationRules as static members on the ViewModel, for example. Especially for ValidationRules on the BindingGroup, you could even get access to the ViewModel instance and its private members that way. – hbarck Nov 23 '12 at 19:01
2

I have implemented the IEditableObject on my ViewModels and I make a copy of the fields when entering Edit mode by invoking an EditCommand.

I also have SaveCommands that can be called in when confirming the edit. Or use a CancelEdit command to revert to the copied values.

Emond
  • 50,210
  • 11
  • 84
  • 115
  • I use an implementation of a memento that uses reflection to automatically save/restore fields marked with a particular attribute - nice and simple – Steve Greatrex Nov 11 '11 at 16:14
  • I generate my ViewModels so I do not have to write the boring copy-code and do not suffer the slowness of reflection – Emond Nov 11 '11 at 16:16
  • The slowest part of reflecting is getting the property definitions, which you can cache per-type so its not too bad a hit. Still, auto-generation is a good option too – Steve Greatrex Nov 11 '11 at 16:38
-1

The key thing is the model should be able to rollback the user changes. How do you do it is really a matter of taste. You can go back to its unchanged state by uisng a 'pristine' copy (not all objects are easily clonable) you can re-query the database, in which can you've a chance to end up with something different to what you initially attempted to edit. There's no universal solution for the problem.