WPF databinding with the POCO Template

Update: with the new version of the POCO template available in Visual Studio Gallery (see here for more information), there is no need for this workaround. We decided to change the collection type for navigation properties to be based on ObservableCollection<T>, so that an IListSource implementation shouldn’t be required anymore.

The new support for POCO in Entity Framework seeks to enable better ways of coding application domain logic without polluting domain classes with persistence concerns. Persistence Ignorance can in fact improve maintainability, testability and evolvability of an application by making it possible to write domain classes that the contain domain logic and nothing more.

Persistence isn’t however the only common infrastructure service that might affect how you write your classes. Others, such as databinding and serialization, sometimes require more than POCO types to work really well.

Disclaimer: I am not trying to enter a debate on whether you should use domain entities directly in databinding and serialization, I am aware of the recommended patterns :)

For instance, to get databinding to fully work with a domain model, each object and collection type has to implement a number of interfaces for things like change notification, type description, capability negotiation, etc. That said, a decent level of databinding support can be achived with simple POCO types and collection types that implement IList, such as List<T>.

In the POCO Template that is included in the Entity Framework Feature CTP 1, we use T4 code generation to produce POCO entity classes and a “typed” ObjectContext class based on an Entity Data Model. The POCO Template emits a special collection type named FixupCollection that has the capability to synchronize changes on both sides of a relationship (typically a one-to-many relationship is represented as a collection on the one side, and as a reference in each object of the many side). But as a colleague of mine found today, Since FixupCollection derives from ICollection<T> and not IList<T>, WPF databinding will not work with it in read-write scenarios.

If you try to bind to a collection emitted by the POCO Template (i.e. in a master-detail form), and the you try to edit it, you will run into this exception message:

'EditItem' is not allowed for this view.

The exception indicates that WPF considers that the collection is read-only.

Here is a way to overcome this:

  • Extend FixupCollection in a partial class to implement IListSource.
  • The implementation of IListSource.GetList has to return a binding list. For instance, I implemented a custom ObservableCollection that has the necessary hooks to update the underlying FixupCollection whenever elements are added or removed.
  • Currently, this doesn’t work the other way around. For instance, when entities added or removed in the underlying collection, the ObservableCollection is not updated.

Here is the code:

using System.Collections.ObjectModel;
using System.ComponentModel;
//TODO: update the namespace to match the same as the code-gen
//FixupCollection
namespace Model
{
public partial class FixupCollection<TFrom, TTo> : IListSource
{
bool IListSource.ContainsListCollection
{
get { return false; }
}

System.Collections.IList IListSource.GetList()
{
return new FixupCollectionBindingList<TFrom, TTo>(this);
}
}

public class FixupCollectionBindingList<TFrom, TTo> :
ObservableCollection<TTo>
{
private readonly FixupCollection<TFrom, TTo> _source = null;

public FixupCollectionBindingList(
FixupCollection<TFrom, TTo> source)
: base(source)
{
this._source = source;
}

protected override void InsertItem(int index, TTo item)
{
_source.Add(item);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
_source.Remove(this[index]);
base.RemoveItem(index);
}
}
}

Hope this helps,

Diego