Thursday, January 11, 2007

Bridge the Gap Between Your NHibernate Collections and WPF UI

While working on a pet software development project of mine, I needed to bind the entity collections I retrieve from my NHibernate back-end to the WPF (Avalon) list controls in my application UI. Since the default collection mapping yields an IList<> collection, it can be bound to the list control successfully and its items will be displayed as advertised. In addition, WPF list controls will be updated automatically (meaning, without writing additional code) when the bound collection's contents change by items being added, removed or reordered. This looks like manna from the heavens, until I made this discovery: that only applies to collections which implement the INotifyCollectionChanged interface. Sounds like a great feature; however NHibernate's collections do not support this interface out-of-the-box. The manna turns to ash in our mouth, so to speak.

Fortunately, all is not lost. This whiz-bang feature can be leveraged with an NHibernate data layer if you are willing to get your keyboard and mouse fingers a bit dirty. NHibernate 1.2 provides the IUserCollectionType interface so that a custom collection type can be developed and referenced when defining a collection in your entity mapping configuration. This means that a new collection class can be defined which implements this interface combined with INotifyCollectionChanged to create an observable collection which will auto-magically update the display of any WPF list control!

Getting custom collections which are usable by NHibernate is a bit tricky at first, so I've included a project which demonstrates how I accomplished it. A few simple domain model entities are mapped to DB tables using NHibernate, one of which utilizes a custom collection. It can be bound to a WPF list control and take advantage of all the nice databinding features. The custom collection also supports lazy-loading as long as you have 'prox-ified' your domain entity classes by declaring all the public properties and methods as virtual, which is the typical procedure as described in the NHibernate documentation.

You can download the demo project here. It contains the source code for the custom persistent and transient collection classes. I've also provided a class diagram which outlines my approach to the solution. There is also an WPF UI project that provides some basic functions to play with the collection contents. You can observe how the UI reacts to those changes without any user-written code to do so.

NOTES:

  • You will need the latest NHibernate 1.2.0, .NET 3.0 Framework and SQL Server 2005 Express installed to use this project.
  • Remember to change the absolute path of the database in the hibernate.cfg.xml for your local machine. This file is located in the Library project.
  • This post assumes that you're already familiar with the basics of both NHibernate and WPF technologies; surf to their respective websites for more information on getting started.