Child Collections in Asp.Net Custom Controls

I have been developing custom web controls for many years now and I am just now getting comfortable with many of the advanced features afforded by the rich System.Web.UI.WebControls namespace. One feature I have implemented many different times over the years is having a web control which contains a list of sub items. For example, the Asp.Net GridView’s collection of Columns or the DropDownList’s collection of ListItems.

<asp:GridView ID="grid" runat="server"> 
        <asp:BoundField /> 
        <asp:ButtonField /> 

There is so many things going on it a control like this that just seem like magic. How are the child items persisted in ViewState? How does the control know how to parse the child items? What if the whole world were a power ranger?


I have created a couple of classes that really simplify the process of creating lists of child items. The first of which is the class StateManagedItem. This class is the base class for all the objects which you wish to use as "Child Items" (like grid view columns or list items).

In order to manage state in Asp.Net, you have to implement the IStateManager interface. This interface allows objects to participate in the process of saving and retrieving things from ViewState. In order to generalize the whole process, I needed on other method to set an item as "Dirty" so I created the following interface:

public interface IStateManagedItem : IStateManager 
    void SetDirty(); 

So now we have the base interface for all state managed items. So here is the what the base class definition looks like:

public abstract class StateManagedItem : IStateManagedItem

This class provides it’s own ViewState for items to save their state in which essentially allows "Child Items" to save their state just like custom web controls do. To illustrate this concept, lets create an example class called Appointment which will hold information about a calendar appointment.

public class Appointment : StateManagedItem

The definition for this class is very simple. Here is how the properties are implemented:

public DateTime? Start 
        object o = ViewState["Start"]; 
        return o == null ? null : (DateTime?)o; 
    set { ViewState["Start"] = value; } 

If you are familiar with using ViewState to store web control properties, this syntax should look fairly familiar. That that is all there is to our child item.


The next helper class is a base class for the collection of items. In our example, we need a collection of Appointments. For this purpose, I have created a StateManagedCollection<T> class which can be used to hold the child items.

public abstract class StateManagedCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IStateManager, 
    IList, ICollection 
    where T : class, IStateManagedItem, new()

If you are not familiar with generics and generic constraints, this is basically a list class which requires the child items to be a class (not a struct), derive from IStateManagedItem, and to have a default constructor.

So to create our list of Appointments, all we need to do is the following:

public class AppointmentCollection : StateManagedCollection<Appointment> 

That is it as far as the AppointmentCollection class goes. It doesn’t require any more code.

Sample Control

So lets finish the example by creating a custom control which displays a list of Appointments. First we will derive from Composite Control:

[ParseChildren(true), PersistChildren(false)] 
public class AppointmentControl : CompositeControl

Note the ParseChildren and PersistChildren attributes, these are required to tell Asp.Net how to parse the markup inbetween the start and end tags of your control. This is part of the "Magic" I mentioned earlier.

Next, make a member of the class which is an AppointmentCollection:

private AppointmentCollection appointments = null;

And a public property to access that collection:

public AppointmentCollection Appointments 
        if (appointments == null) 
            appointments = new AppointmentCollection(); 
            if (base.IsTrackingViewState) 
        return appointments; 

This property also must have a couple of attributes – Mergable and PersistenceMode. These basically tell Asp.Net and Visual Studio how to handle and persist this property.

To use this control, first place the proper includ directive on your page:

<%@ Register TagPrefix="web" Namespace="Web.Example.Appointment" %>

Now we can declare our control markup as:

<web:AppointmentControl id="appointmentList" runat="server"> 
        <web:Appointment Start="1/6/2007 8:00 AM" End="1/6/2007 11:30 AM" Description="Breakfast" /> 
        <web:Appointment Start="5/12/2007 9:30 AM" End="5/12/2007 9:45 AM" Description="Meeting" /> 
        <web:Appointment Start="5/12/2007 10:00 AM" End="5/12/2007 10:30 AM" Description="Break" /> 

I won’t go into the render code (you can download the source code to see all the gory details) but here is how the control renders:

You have 3 appointment(s)

  • Breakfast – (01/06/2007 08:00:00 – 01/06/2007 11:30:00)
  • Meeting – (05/12/2007 09:30:00 – 05/12/2007 09:45:00)
  • Break – (05/12/2007 10:00:00 – 05/12/2007 10:30:00)

You can download the full source code here. Hope this helps dispell some of the "Magic" of Asp.Net controls.

kick it on


7 Responses to Child Collections in Asp.Net Custom Controls

  1. Will says:

    Hi Luke, good work! Are you looking for a new job? We’re a local firm and hiring, let me know.


  2. Ian Kulmatycki says:


    These base classes are a great idea. Well done.


  3. Chris says:

    I have been messing with the composite control examples online for days, sigh . . . Downloaded your code and bam done, simple elegant works like a charm, my composite control works great. Now I can sleep. Thanks

  4. Steve says:

    Just what I was looking for. There doesn’t seem to be a lot of info on the net about how this is done, so thanks for this write-up!

  5. naisioxerloro says:

    Good design, who make it?

  6. […] enums as well as some parsing methods similar to these. I have written about DelimitedList and the state managed classes before. I make heavy use of QueryStringHelper to build the query string which  represents the […]

  7. James says:

    Hi, the download link is broken!!! Your article is excellent and I desperately would like to see the source. Could you please check it? Thanks!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: