I’m working on an ASP.NET 2.0 project that uses CSS to stylize the UI. I needed to include <COLGROUP> elements in the output from GridView controls, but alas, GridView doesn’t support <COLGROUP>. (The ASP.NET team is aware of this, and a future version of GridView will, in all likelihood, support <COLGROUP>.) So I built a quick-and-dirty custom control–a GridView-derivative–that supports <COLGROUP>. With the custom control, you can include a <COLGROUP> in the GridView definition like this:

<custom:ColGroupGridView … runat=”server”>
    <ColGroupTemplate>
        <COL class=”itemid” />
        <COL class=”cover-image” />
        <COL class=”title” />
        <COL class=”number” />
        <COL class=”year” />
        <COL class=”rating” />
        <COL class=”cgc-rating” />
        <COL class=”description” />
    </ColGroupTemplate>
  …

</custom:ColGroupGridView>

And here’s the source code for the custom control:

internal class ColGroup : WebControl, INamingContainer
{
    internal void RenderPrivate(HtmlTextWriter writer)
    {
        writer.Write(“<COLGROUP>”);
        base.RenderContents(writer);
        writer.Write(“</COLGROUP>”);
    }
}

public class ColGroupGridView : GridView
{
    private ColGroup _ColGroup = null;
    private ITemplate _ColGroupTemplate = null;

    [TemplateContainer(typeof(ColGroup))]
    public virtual ITemplate ColGroupTemplate
    {
        get { return _ColGroupTemplate; }
        set { _ColGroupTemplate = value; }
    }

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        _ColGroup = new ColGroup();
        ColGroupTemplate.InstantiateIn(_ColGroup);
    }

    protected override void Render(HtmlTextWriter writer)
    {
        // Get the base class’s output
        StringWriter sw = new StringWriter();
        HtmlTextWriter htw = new HtmlTextWriter(sw);
        base.Render(htw);
        string output = sw.ToString();
        htw.Close();
        sw.Close();

        // Insert a <COLGROUP> element into the output
        int pos = output.IndexOf(“<tr”);

        if (pos != -1 && _ColGroup != null)
        {
            sw = new StringWriter();
            htw = new HtmlTextWriter(sw);
            _ColGroup.RenderPrivate(htw);
            output = output.Insert(pos, sw.ToString());
            htw.Close();
            sw.Close();
        }

        // Output the modified markup
        writer.Write(output);
    }
}

Yes, it’s a bit of a hack, but it works, and it’s not terribly inelegant.