Introduction
Most applications directly or indirectly deal with databases and collections of objects. These collections are bound to some UI shown to the user, updated, saved... Well, you know the drill. Here, I would like to share the approach that works best for me.
ListWithEvents<T>
First of all, I needed to be able to know when an item was added, removed or modified in the collection. None of the provided collections could handle that (or have I just missed it?). So, I made my own: ListWithEvents<T>
. All I did was overload the existing methods of the List<T>
class and introduce the required events.

There is nothing really fancy about this. The only thing I have added to the collection is an ability to perform batch actions that raise only a single event. To switch to batch update, call SuppressEvents()
. Once events are suppressed, the collection tracks events that would have been raised otherwise. As soon as the ResumeEvents()
method is called, the collection fires up those events, one of each kind.
MutableObject
To start with, I wanted to have a base object, so I made one: MutableObject
. The class has only a few properties, events and methods. The object is also capable of serialising and deserialising itself as XML.
There is nothing really fancy about those except the implementation of Clone()
. I needed a real deep-clone functionality and, considering it is a base class, the last thing I wanted was to provide implementation in every descendant of my MutableObject
.
So, after some Googling, I came across an article by Renfield on it. I took the guy's idea and, having fixed a few problems and enhanced it along the way, I made my MutableObject
cloning all of its writable properties and fields. One thing that should be noted here, however, is that reference-type properties will only be deeply cloned if they implement the IClonable
interface.
ListOfMutableObjects<T>
Now creating a ListOfMutableObjects<T>
collection seems like a very reasonable step. You need to overload a number of methods handling item addition, removal and modification wiring to/unwiring from the item's Modified
event.
I mentioned the batch action mode earlier. This is particularly useful when you update a number of properties for some item in the collection. For instance:
class MyObject : MutableObject
{
private int p1, p2;
public int P1
{
get
{
return this.p1;
}
set
{
if (this.p1 != value)
{
this.p1 = value;
this.OnModified(EventArgs.Empty);
}
}
}
public int P2
{
get
{
return this.p2;
}
set
{
if (this.p2 != value)
{
this.p2 = value;
this.OnModified(EventArgs.Empty);
}
}
}
}
Assuming that there is ListOfMutableObjects<MyObject> mylist
and you have wired up the ItemModified
and/or CollectionModified
events, you will have the following code to modify an item in the collection:
mylist.SuppressEvents();
mylist[0].P1 = 5;
mylist[0].P2 = 10;
mylist.ResumeEvents();
This way, you will have only one event notification instead of two.
Update to Version 1.3.1
Some time ago, I realised a few shortfalls that got fixed in this version. To start with, I have made the list thread-safe and exposed a public SyncRoot
property. Next, I refactored the CollectionModified
event to be fired by a designated method: OnCollectionModified()
. I have also changed the signature of the event to EventHandler<ListModificationEventArgs>
and created a ListModificationEventArgs
class. Thirdly, I have discarded all of the custom event handlers and replaced them with EventHandler<T>
handlers, where T represents appropriate event arguments.
Another minor change includes the marking of all shadowed methods with the "virtual" keyword, providing the class descendants with the opportunity to override the methods rather than shadowing them again.
At one point when I was building a UI with a PropertyGrid control and an instance of ListWithEvents
, I noticed that the Collection Editor UI didn't seem to be calling my Add()
methods. So, to address the problem I had to provide an explicit implementation of the IList.Add()
method. After that, the UI would correctly wire up -- and subsequently fire -- events to new items.
Perhaps the last addition to the library worth mentioning is the ClonableListWithEvents<T>
class. You can probably guess from the name that it is a list with events for objects implementing the IClonable
interface.
public class ClonableListWithEvents<T> : ListWithEvents<T>, ICloneable
where T : ICloneable
{
...
public virtual ClonableListWithEvents<T> Clone();
}
History
- 9 Mar 2007 - Initial submission; version 1.0.0.0
- 6 Jul 2007 - Updated to version 1.3.1.0
- 7 Aug 2007 - Updated to version 1.3.1.1
Final Words
Well that's all folks. I hope someone will find it useful.