Sample: IEditableObject Adapter
Often we find objects that we may not have full control over, but which we wish to use in our UI layer. Some examples are:
- LINQ to SQL classes, generated by the DBML designer
- WCF/web service message classes, generated by WSDL.exe, svcutil.exe or Add Web Reference
- Classes from third party object models - TFS client objects, SharePoint objects, SMO objects, etc
Some of these provide partial classes, which give you some flexibility, and others allow you to drop the tools altogether. For instance, you don’t have to use the DBML designer with LINQ to SQL. Unfortunately, dropping the tools can mean quite a bit of manual work. What’s a girl to do?
In this post, I will present another option: I’ll make use of CustomTypeDescriptors to add an IEditableObject implementation to a LINQ to SQL DBML design-generated Contact class from the AdventureWorks database.
IEditableObject
IEditableObject is an interface that’s been around since the early days of .NET. By implementing it, you can make changes to a data-bound object, and then choose to commit them or roll them back (usually via Save/Cancel buttons). Under the hood, we usually implement this via the memento design pattern.
IEditableObject requires you to implement the following methods:
- BeginEdit()
- CancelEdit()
- EndEdit()
BeginEdit can be called manually, or in the case of the DataGridView, it will be called automatically if implemented. This is the part where you normally take your "snapshot" of the object’s state. CancelEdit is then called to rollback the changes, and EndEdit to accept them. Note that BeginEdit can be called multiple times (some weirdness with the DataGridView), so you should only honor the first call.
A common problem with editing data-bound objects is that when you edit the UI, changes are pushed to the underling properties on the object. If that object is visible elsewhere - such as in a list in another Window - you’ll see the changes reflected there too, even if the user hasn’t "committed" their changes yet. That can be confusing to users.
CustomTypeDescriptors
The data binding systems in both Windows Forms and WPF don’t go through reflection to find your properties, but instead make use of the TypeDescriptor class. This class allows you to describe how an object looks - the properties it has, the events it has, and the attributes it has. You can’t fake interfaces, but you can fake a TypeConverter which converts to the target interface - a clever way to support interfaces the object doesn’t expose.
Some examples of how you might use TypeDescriptors are:
- To add fake properties to an object
- To add fake events (<PropertyName>Changed events, for example)
- To provide TypeConverters to simulate implementation of interfaces
Note that when you provide a custom TypeDescriptor, in is honored both at runtime and at design time, as you’ll see below.
Idea
Instead of implementing IEditableObject on every class, we’ll create a class that wraps our LINQ to SQL designer-generated objects following the Adapter design pattern. It will implement IEditableObject for us, as well as INotifyPropertyChanged, and use a CustomTypeDescriptor to expose the properties of the object it wraps. A few goals:
- When properties are changed on the adapter, they aren’t committed to the object being wrapped until EndEdit() is called
- The object should make minimal use of reflection
- It should be easy to add extra UI-only properties to the object
- Full designer support (especially important for Windows Forms)
- Minimal code to use the functionality
Implementation note: Since we’ll need to use reflection to push changes to/from the underlying properties on the object, we’re going to generate delegates to do the job for us, and we’ll cache those delegates for use later. This way, we only wear the cost of reflection once. Thanks to Corneliu Tusnea for the idea behind this implementation.
Using the Code
We’ll call the adapter EditableAdapter<T>. Assuming you have a Contact class generated by LINQ to SQL, here’s how you would use the EditableAdapter<T>:
public class EditableContact : EditableAdapter<Contact>
{
public EditableContact(Contact contact)
: base(contact)
{
}
}
You wouldn’t need to write this class at all in WPF, but the Windows Forms designer does not allow us to bind to generic objects. This class does give us the chance to provide additional UI-only properties, however, like this:
public class EditableContact : EditableAdapter<Contact>
{
public EditableContact(Contact contact)
: base(contact)
{
}
public string FullName
{
get
{
return string.Format("{0} {1}",
this.WrappedInstance.FirstName,
this.WrappedInstance.LastName);
}
}
}
Note that we didn’t have to re-implement every property from the Contact class on our adapter class - that will all be done at runtime through the type descriptor.
Now we can use the Windows Forms designer to bind to the object:
Note that the properties appear in the Data Sources window, including our custom FullName property, and the HasChanges property which is provided by the EditableAdapter.
The HasChanges property is a bindable boolean value that indicates whether any property values have been changed. We’ll bind that up to the Apply and Reset button’s Enabled properties - the buttons will only be enabled when you’ve got pending changes:
Finally, wire up the form’s code-behind to handle the various buttons:
public ContactEditDialog(EditableContact contact)
{
InitializeComponent();
editableContactBindingSource.DataSource = contact;
contact.BeginEdit();
}
public EditableContact Contact
{
get { return editableContactBindingSource.DataSource as EditableContact; }
}
private void OKButton_Click(object sender, EventArgs e)
{
this.Contact.EndEdit();
this.DialogResult = DialogResult.OK;
}
private void ApplyButton_Click(object sender, EventArgs e)
{
this.Contact.EndEdit();
this.Contact.BeginEdit();
}
private void ResetButton_Click(object sender, EventArgs e)
{
this.Contact.CancelEdit();
}
private void CancelButton_Click(object sender, EventArgs e)
{
this.Contact.CancelEdit();
this.DialogResult = DialogResult.Cancel;
}
And you’re done. IEditableObject implementations on designer-generated classes with minimal code
Download the sample below and have a look. Notice that:
- The changes don’t appear in the DataGridView until we click Apply.
- If we edit something the Apply and Reset buttons become enabled, however if we then change it back to what it was, the buttons disable again.
- If we Cancel or Reset, the changes aren’t applied.
Download the code (ZIP)
(Warning: This is a VS 2008 solution)
Summary
Custom type descriptors are a great way to leverage code. You can build the behavior into a couple of smart adapters or type descriptors/converters, and minimize the code you need to write over and over again. As I mentioned, the above code would work in WPF, and you wouldn’t even need to code the wrapper class. Type descriptors can be a little tricky though, so give yourself some time. It’s well worth the investment.
CustomTypeDescriptors aren’t a solution to every problem, however. They provide a bit of a barrier between the objects and the UI, but they aren’t a complete layer of insulation in the way an adapter layer would be. Use at your own risk!
By the way, I’ll be demonstrating these and other data binding tricks at CodeCampOZ 2008. See you there!
Filed under: Binding


Great idea Paul!
I used to write object wrappers to communicate with objects of this kind in WPF (I’ve written about it in my blog, but unfortunately only in my native language(inspired by Josh Smith)), but your approach is just awesome!
P.S. I am planning to keep an english mirror of my blog here: http://robbbloggg.blogspot.com/
I don’t know if there is a reason of writing in my native language as I have two visitors a day on the avarage… =\
Hi Robert,
There are a lot of interesting class diagrams on your blog, but the Google translator doesn’t do the text justice
I for one would subscribe to your English mirror.
Paul
Hi Paul,
I actually started on something very similar to this a couple months ago, though I never finished it. The primary differences were that I stored the uncommitted values in the custom PropertyDescriptor instances, and that those PropertyDescriptors also listened for changes to the source object. My ObjectView (akin to your EditableAdapter) also implemented IRevertibleChangeTracking, IDataErrorInfo, IValidator, and IComponent.
You can check out the source if you like: http://www.armadafleetcommand.com/botf/strobel/ObjectView.zip
Keep in mind that I never really finished this, so there are probably some unaddressed issues. For instance, I believe the caching mechanism in ObjectViewTypeDescriptorProvider never releases old items.
This is awesome stuff. I can definately use this in my app and avoid having to write lots of code. Thanks Paul!
Very good article!!!
But I have a question:
what about child collection objects? I mean, if I have business object “EditableOrder ” (from your base class) which has an EntitySet “OrderDetails” (and for example each “OrderDetail” has an EntitySet “OrderDetailLines”) what about Undo of child objects?
Thank’s in advance!
[…] Custom TypeDescriptor example […]
Great work Paul,
I love the HasChanges property, I haven’t often seen state feedback (i.e. the Apply and Reset buttons become enabled) in .NET UI’s, which is great pity.
Do you know of anyway of finding the state for inserts to a BindingSource?
At a quick glance the only way I can see to do it is to try and keep track of insertion state externally or make a my own copy of BindingSource and expose the
private int addNewPos
Hi,
unfortunally i could not download the sample. Could you relocate this zip please?
@Paul
Great work!
@Constantin
The zip link points to www.paulstovell.net instead of www.paulstovel.com. Guess the .net domain is down or something, so it cannot redirect to .com.
The actual link to the zip file is: http://www.paulstovell.com/blog/wp-content/uploads/2008/03/bindingorientedadapters.zip