I previously blogged about how to use the C# INotifyPropertyChanged interface with
BindingList<T> instances so that your lists properly fire the
ListChanged event with a
In that post, I also alluded to the fact that
BindingList<T> is flawed with regard to serialization of BindingList<T> subtypes. The problem has to do with the fact that
BindingList<T> listens for
PropertyChanged events on any of its list items that implement
INotifyPropertyChanged. However, because event handlers are not serializable, those listener connections are lost during the serialization process for subtypes, and they don’t get rewired when the list is deserialized. It’s straightforward to do that, but the implementation is missing from the .NET SDK, so we have to write it ourselves.
For a code example that shows how this flaw behaves, check out Demonstrating BindingList Serialization Bug.
Interestingly, this problem doesn’t show up with concrete instances of
BindingList<T> — only its subtypes. [update: some readers report the problem still exists with concrete BindingLists – could it be explained by different patch levels on the framework?] Why would you ever want to extend
BindingList<T>? Perhaps it’s to add domain specific features, or perhaps it’s to add generic sorting capabilities like the
SortableBindingList<T> class described in this great article by Michael Weinhardt.
On my own projects, I use a fairly sophisticated
BindingList<T> subtype that fixes a number of shortcomings. For this post, however, I’ll focus on the serialization issue.
What I’ve done is I’ve extended
BindingList<T> and added a method annotated with the
OnDeserialized attribute like this:
public class FixedBindingList<T> : BindingList<T>
private void OnDeserialized(StreamingContext context)
List<T> items = new List<T>(Items);
int index = 0;
// call SetItem again on each item to re-establish event hookups
foreach (T item in items)
// explicitly call the base version in case SetItem is overridden
StreamingContext parameter is a requirement of the
OnDeserialized attribute, but everything else is straightforward. After .NET has finished deserializing the list, we iterate over each of the items and invoke
SetItem(). These items, of course, are already on the list at this point. However, it’s the implementation of
that handles the wiring of event listeners to the
PropertyChanged event of any items implementing
INotifyPropertyChanged. Because we’re essentially “replacing” list items with references to the same item, there are no other side effects to the list.
One final note is to point out that I explicitly invoke the supertype implementation of
SetItem() using the
SetItem() is a virtual method, and it’s possible that a more elaborate extension of
BindingList<T> may choose to override it. That’s okay, but it might unintentionally introduce unwanted behavior on deserialization. Thus, we avoid that problem by forcing the call to be handled directly by the base class.