Update 29/07: The project was updated, there was a minor bug in the object changed notifier.
In continuation of a previous post -
WPF – Editing Mode with Save and Cancel Capability
In this post I will demonstrate an elegant and simple solution that you can utilize regarding the first option presented in the previous post.
The Use-Case
If you want to open an editable view over an existing read-only view with cancel capability, you usually wish you could use the same ViewModel instance as the DataContext.
However, this means that changes are reflected in the read-only view, plus, how would you implement the cancel operation?
The following solution demonstrates a dynamic proxy that I had written that you can use to provide elegant solution in cases where your ViewModel is simple.
By ‘simple’ I mean the ViewModel contains a set of self-contained properties (their setters don’t affect anything else) and that there are no commands needed for the editable view.
The common approach for such simple cases is defining the bindings with UpdateSourceTrigger set to ‘Explicit’.
My solution is simpler, it doesn’t require you to do that, thus you need not update the bindings upon save and such.
Moreover, my solution still provides a way to support IDataErrorInfo on the ViewModel!
The right pane contains the read-only view:
| When clicking Edit, a dialog is shown:
|
Let’s see the code
When the user clicks ‘Edit’, the code opens the dialog with the DataContext set as follows -
Code Snippet
var proxy = new ViewModelProxy<EmployeeViewModel>(emp);
editView.DataContext = proxy;
When the user chooses Save or Cancel in the dialog, the following code merges the changes into the actual EmployeeViewModel -
Code Snippet
bool? result = editView.ShowDialog();
if (result.GetValueOrDefault())
{
proxy.AcceptChanges();
}
That is all that is needed! Nothing else!
The proxy has another method - ‘RejectChanges’ if you need to reject the changes and go back to the state of the original EmployeeViewModel.
How is the magic done?
I implemented the ViewModelProxy using the DynamicObject that comes with .NET 4.0, sweet.
This can be done in previous .NET framework versions too. It would require more code though, you could implement a dynamic property bag with a type descriptor.
The ViewModelProxy performs mainly the following parts -
- When a property is set on it – it stores it into a local dictionary and notifies upon property changed
- When a property is requested from it – returns the value from the local dictionary if present, or from the source ViewModel otherwise.
- AcceptChanges applies the local dictionary values to the source ViewModel
- RejectChanges clears the local dictionary and notifies upon property changes.
- I mentioned it above, my solution supports IDataErrorInfo, make sure to check out the sample
You can download the source here - Zuker.WpfSamples.zip.
In the next post I will demonstrate another infrastructure I had implemented that you can use for more advanced scenarios.