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.
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.
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
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
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
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
if (this.p1 != value)
this.p1 = value;
public int P2
if (this.p2 != value)
this.p2 = value;
Assuming that there is
ListOfMutableObjects<MyObject> mylist and you have wired up the
CollectionModified events, you will have the following code to modify an item in the collection:
mylist.P1 = 5;
mylist.P2 = 10;
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
public class ClonableListWithEvents<T> : ListWithEvents<T>, ICloneable
where T : ICloneable
public virtual ClonableListWithEvents<T> Clone();
- 9 Mar 2007 - Initial submission; version 188.8.131.52
- 6 Jul 2007 - Updated to version 184.108.40.206
- 7 Aug 2007 - Updated to version 220.127.116.11
Well that's all folks. I hope someone will find it useful.