One of the banes of my life as a professional developer is handling grid editing where it can react intelligently to the user cancelling a change in the middle of an add or edit. Fortunately, if you know where to look, .NET can do a lot of the heavy lifting for you. With a little bit of IEditableObject goodness and a couple of helper classes, it’s now easy to add change handling to your WPF applications.
The attached project contains a library with two classes in it that you can use to do the work for you. The first class, EditableObject, manages the commit and rollback phases. The behaviour of this class is interesting, so I’d like to take a few minutes to go over it with you. The first thing to note is that it’s abstract, so your data classes inherit from it. When you start an add or edit operation, a copy of the current data class is created and the values are stored in the copy before the edit can progress. This gives us a copy to go back to without having to manually copy fields out. It uses reflection to do this, which can be a little bit slow on complex types, but when you’re dealing with reflecting on one object it’s not too bad and it was a compromise I was prepared to live with in return for the flexibility it provides.Important note: As we’re using reflection here, I’m only serializing the fields of the current object so the hierarchy doesn’t get traversed. This means that your dataclasses must derive from EditableObject directly in order to get access to all the features of this wrapper.
EditableObject implements the INotifyPropertyChanged interface with a bit of a twist. In normal operations, you would raise the PropertyChanged event as soon as you changed the property, but we don’t want this to happen until we’ve committed the edit/add. This means we have to step outside the normal behaviour a little bit, and to do this I’ve changed the usual implementation of INotifyPropertyChanged so that it just records the properties that have changed – then it plays them back when the edit is committed. Obviously, if it’s rolled back then the notification doesn’t go ahead.
The second class, EditableCollectionHandler, encapsulates IEditableCollectionView which was introduced in .NET 3.5 SP 1. Basically, this is a view that supports adding, editing and removing items from a collection. The add and edit are transactional, so we can hook this up to EditableObject directly. It provides the following methods, Add, Edit, Remove, CommitChanges and CancelChanges as well as two properties; DefaultView and EditView.
In the sample, I’ve created a ListBox inside a grid. The grid contains two DataTemplates to be used with the ListBox, the default template used to display the data, and the EditTemplate, to be used when we are adding or editing a line of data.
When you set up the link from your WPF application to EditableCollectionHandler, you specify the object you want the collection view to work against, the container of the templates and the type of item you want to specify for editing the items when you are adding or editing. You also set up the name of the default template and the edit template (if you have one), and then you’re good to go.
- Visual Studio 2008
- .NET 3.5 SP 1
Be sure to change the extension from doc to zip and then uncompress it.
One thought on “Reusable transaction handling in WPF with IEditableCollectionView.”
Note that this will only work if the derived class has a constructor that accepts no parameters else Activator.CreateInstance(this.GetType(), false); will fail.
Another alternative that gets around this (http://www.codeproject.com/KB/database/IEditableObject.aspx) is to replace “private EditableObject _copy;” with a Hashtable.