Click here to Skip to main content
15,881,204 members
Articles / Programming Languages / C#
Article

Generic List of Mutable Objects with Events

Rate me:
Please Sign up or sign in to vote.
4.78/5 (24 votes)
7 Aug 2007CPOL3 min read 62.7K   248   40   18
Implementation of an enhanced List<T> of mutable objects with events

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.

Screenshot - listwithevents.jpg

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.

Screenshot - mutableobject.jpg

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.

Screenshot - listofmutableobjects.jpg

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:

C#
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:

C#
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.

C#
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMuch Thanks Pin
MerrillMarie9-Nov-08 7:23
MerrillMarie9-Nov-08 7:23 
GeneralSuppressEvents doe not seem to work Pin
antoschka13-Oct-08 2:36
antoschka13-Oct-08 2:36 
GeneralRe: SuppressEvents doe not seem to work Pin
Igor Velikorossov22-Oct-08 20:26
Igor Velikorossov22-Oct-08 20:26 
GeneralBindingList & INotifyPropertyChanged Pin
bxb26-Oct-07 4:47
bxb26-Oct-07 4:47 
QuestionCan the CtrlSoft.dll be bundled and redistributed with proprietary software ? Pin
mali7631-Aug-07 7:26
mali7631-Aug-07 7:26 
AnswerRe: Can the CtrlSoft.dll be bundled and redistributed with proprietary software ? Pin
Igor Velikorossov2-Sep-07 4:14
Igor Velikorossov2-Sep-07 4:14 
GeneralRe: Can the CtrlSoft.dll be bundled and redistributed with proprietary software ? Pin
reflex@codeproject26-May-09 8:59
reflex@codeproject26-May-09 8:59 
GeneralRe: Can the CtrlSoft.dll be bundled and redistributed with proprietary software ? Pin
Igor Velikorossov27-May-09 2:16
Igor Velikorossov27-May-09 2:16 
GeneralObservableCollection Generic Class [modified] Pin
tarasn9-Aug-07 5:47
tarasn9-Aug-07 5:47 
GeneralRe: ObservableCollection Generic Class Pin
Igor Velikorossov13-Aug-07 15:07
Igor Velikorossov13-Aug-07 15:07 
GeneralCloning Pin
Ernest Bariq17-Mar-07 14:13
Ernest Bariq17-Mar-07 14:13 
GeneralRe: Cloning Pin
Igor Velikorossov18-Mar-07 13:08
Igor Velikorossov18-Mar-07 13:08 
QuestionDo you know the System.Collections.ObjectModel namespace ? Pin
Declercq Dirk12-Mar-07 2:25
Declercq Dirk12-Mar-07 2:25 
AnswerRe: Do you know the System.Collections.ObjectModel namespace ? Pin
Sebastien Lorion12-Mar-07 5:45
Sebastien Lorion12-Mar-07 5:45 
GeneralBindingList Pin
purplepangolin9-Mar-07 4:50
purplepangolin9-Mar-07 4:50 
GeneralRe: BindingList Pin
Igor Velikorossov18-Mar-07 13:10
Igor Velikorossov18-Mar-07 13:10 
Generalcomponent based software modeling Pin
Andreas Hollmann9-Mar-07 3:00
Andreas Hollmann9-Mar-07 3:00 
GeneralRe: component based software modeling Pin
Igor Velikorossov9-Mar-07 3:06
Igor Velikorossov9-Mar-07 3:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.