Click here to Skip to main content
15,881,204 members
Articles / Web Development / ASP.NET

TitleCheckBoxList - Adding Column Headers / Titles to a CheckBoxList Control

Rate me:
Please Sign up or sign in to vote.
4.64/5 (8 votes)
19 Apr 2007CPOL5 min read 75.3K   1.1K   22   24
Extending the CheckBoxList control to allow ListItems that serve as column headers / titles / category headings and not render a CheckBox.

Screenshot - TitleCheckBoxList1.gif

Introduction

The TitleCheckBoxList control is designed to allow you to insert column headers / titles into a CheckBoxList. The titles are included in the Items collection of the ListControl, but do not render a CheckBox on the form.

This control is useful if you have a number of options that you want to display in a list of checkboxes and you want to group and organize the checkboxes according to the type or category of the option it represents.

Using the Control

Step 1: Add the TitleCheckBoxList.cs class file to your project in the App_Code folder.

You can download this C# class file by clicking the 'Download source code' link at the top of this article.

C#
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;

namespace VwdCms
{
    public class TitleCheckBoxList : CheckBoxList
    {
        public const string TitleValue = "###title###";
        public const string SpacerValue = "###spacer###";

        private Unit _titleWidth;

        public Unit TitleWidth
        {
            get { return _titleWidth; }
            set { _titleWidth = value; }
        }

        protected override void RenderItem(ListItemType itemType, 
        int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
        {
            ListItem itm = this.Items[repeatIndex];
            string val = itm.Value;

            if (val == TitleValue || val == SpacerValue )
            {
                if (repeatIndex == 0)
                {
                    StringWriter sw = new StringWriter();
                    HtmlTextWriter dummyWriter = new HtmlTextWriter(sw);
                    base.RenderItem(itemType, repeatIndex, 
                    repeatInfo, dummyWriter);
                }

                if (val == TitleValue)
                {
                    Label lbl = new Label();
                    lbl.Font.CopyFrom(this.Font);
                    lbl.Font.Bold = true;
                    lbl.Text = itm.Text;
                    if (this.TitleWidth != null)
                    {
                        lbl.Width = this.TitleWidth;
                    }
                    lbl.RenderControl(writer);
                }
                else if (val == SpacerValue)
                {
                    writer.Write(HtmlTextWriter.SpaceChar);
                }
            }
            else
            {
                base.RenderItem(itemType, repeatIndex, repeatInfo, writer);
            }
        }
    }
}

Step 2: Update your web.config file's Controls section (inside the system.web section):

XML
<pages>
    <controls>
        <add tagPrefix="VwdCms" namespace="VwdCms"/> 
    </controls>
</pages>

Step 3: Add a TitleCheckBoxList control to your Web Form:

C#
<VwdCms:TitleCheckBoxList runat="server" ID="cblTitles"
     RepeatDirection="Vertical" RepeatColumns="5" 
     style="font-family:Arial;font-size:8pt;text-align:left;
     border:solid 1px #336699;" TitleWidth="90px" />

Some Examples

You can download the code for these examples by clicking the 'Download demo' link at the top of this article.

Example 1

This example demonstrates how the TitleCheckBoxList will render when all of the columns have the same number of items.

Since we know in advance in this example that we will have five different "Categories" (Titles), we can set the RepeatColumns property of the CheckBoxList to 5 and we get a clean looking display of 5 columns with an equal number of CheckBoxes.

By setting the TitleWidth property of TitleCheckBoxList, we can get the spacing between the columns without having to work with the RepeatLayout of the CheckBoxList.

TitleCheckBoxList renders Titles at the top of each column

Here is the code to load this TitleCheckBoxList:

C#
if (!this.Page.IsPostBack)
{
    // if this is the initial load (HTTP GET) of the page 
    // then put some items in the checkboxlist
    int catNum = 0;
    int itmNum = 0;
    int i = 0;
    ListItem itm = null;

    for (catNum = 0; catNum < 5; catNum++)
    {
        itm = new ListItem("Category " + catNum.ToString(),
            VwdCms.TitleCheckBoxList.TitleValue);
        this.cblTitles.Items.Add(itm);
        itmNum++;

        for (i = 0; i < 6; i++)
        {
            itm = new ListItem("Item " + itmNum.ToString(), 
                itmNum.ToString());

            // select the even ones
            itm.Selected = (itmNum % 2 == 0);
            this.cblTitles.Items.Add(itm);
            itmNum++;
        }
    }
}

Example 2

This example demonstrates how the TitleCheckBoxList will render when the number of items in each category is different.

For some applications, this might be acceptable; for others, it may be necessary to make the display a little bit cleaner. See Example 3 to see how to clean up the display.

TitleCheckBoxList renders Titles at the top of each column

Here is the code to load this TitleCheckBoxList:

C#
if (!this.Page.IsPostBack)
{
    // if this is the initial load (HTTP GET) of the page 
    // then put some items in the checkboxlist

    // this example demonstates how the TitleCheckBoxList will  
    // render when the nubmer of items under 
    // each category is different

    int catNum = 0;
    int itmNum = 0;
    int i = 0;
    int itemCount = 6;
    ListItem itm = null;

    for (catNum = 0; catNum < 5; catNum++)
    {
        itm = new ListItem("Category " + catNum.ToString(),
            VwdCms.TitleCheckBoxList.TitleValue);
        this.cblTitles.Items.Add(itm);
        itmNum++;

        for (i = 0; i < itemCount; i++)
        {
            itm = new ListItem("Item " + itmNum.ToString(), 
            itmNum.ToString());

            // select the even ones
            itm.Selected = (itmNum % 2 == 0);
            this.cblTitles.Items.Add(itm);
            itmNum++;
        }
        itemCount--;
    }
}

Example 3

This example demonstrates how the TitleCheckBoxList will render when the number of items in each category is different, but we can get a clean column display by adding "spacer" ListItems.

TitleCheckBoxList renders Titles at the top of each column

Here is the code to load this TitleCheckBoxList:

C#
if (!this.Page.IsPostBack)
{
    // if this is the initial load (HTTP GET) of the page 
    // then put some items in the checkboxlist

    // this example demonstates how the TitleCheckBoxList will  
    // render when the nubmer of items under 
    // each category is different

    int catNum = 0;
    int itmNum = 0;
    int i = 0;
    int itemCount = 6;

    // getting the itemCountMax in a real world application will be
    // more challenging, you may have to loop through the collection
    // once before looping through and adding list items.
    int itemCountMax = 6;

    ListItem itm = null;

    for (catNum = 0; catNum < 5; catNum++)
    {
        itm = new ListItem("Category " + catNum.ToString(),
            VwdCms.TitleCheckBoxList.TitleValue);
        this.cblTitles.Items.Add(itm);
        itmNum++;

        for (i = 0; i < itemCountMax; i++)
        {
            if (i > itemCount - 1)
            {
                // add a spacer 
                itm = new ListItem(string.Empty, 
                VwdCms.TitleCheckBoxList.SpacerValue);
            }
            else
            {
                itm = new ListItem("Item " + itmNum.ToString(), 
                itmNum.ToString());

                // select the even ones
                itm.Selected = (itmNum % 2 == 0);
            }

            this.cblTitles.Items.Add(itm);

            itmNum++;
        }
        itemCount--;
    }
}

Handling Postbacks

There is a slight difference during postBack processing that you will need to keep in mind when using the TitleCheckBoxList. The underlying CheckBoxList thinks that all of the ListItems in the Items collection are valid CheckBox controls. In fact, they are valid ListItems, but the TitleCheckBoxList's RenderItem method prevents the CheckBox control from being rendered for the title and spacer items.

The result is that your code will need to check for titles and spacers as you iterate through the Items collection to determine which items are checked and not checked.

Here is some example code:

C#
void btnPostback_Command(object sender, CommandEventArgs e)
{
    // loop through the items and add the selected ones 
    // to the "selected" label control and add the 
    // non-selected ones to the "non-selected" label

    // Note: the CheckBoxList control thinks that the 
    // Title items and Spacer items are valid ListItems, 
    // but we want to ignore them when looping through 
    // the collection

    StringBuilder sbSelected = new StringBuilder();
    StringBuilder sbNonSelected = new StringBuilder();

    foreach (ListItem itm in this.cblTitles.Items)
    {
        if (itm.Value != VwdCms.TitleCheckBoxList.TitleValue 
            && itm.Value != VwdCms.TitleCheckBoxList.SpacerValue )
        {
            if (itm.Selected)
            {
                sbSelected.Append(itm.Text);
                sbSelected.Append(", ");
            }
            else
            {
                sbNonSelected.Append(itm.Text);
                sbNonSelected.Append(", ");
            }
        }
    }

    this.lblSelected.Text = sbSelected.ToString();
    this.lblNonSelected.Text = sbNonSelected.ToString();

}

Points of Interest

What the heck is dummyWriter doing in the RenderItem method of TitleCheckBoxList?

I ran into a strange problem when I tried out the overridden RenderItem method - all of the checkboxes in the TitleCheckBoxList were disabled. When I tried it without any title ListItems, the checkboxes were enabled. After a few minutes of experimentation, I figured out that it only happens when the first ListItem is a title. Apparently, the RenderItem method of the base class, CheckBoxList, is doing something when the first ListItem is rendered, and if you don't use the RenderItem of the base class for that first ListItem, all of the checkboxes will be disabled.

I looked at the CheckBoxList class documentation and could not find any way to control this behavior. So, the bottom line is that I need to call the CheckBoxList's RenderItem method on the first ListItem, despite the fact that I really don't want to use it. What I want is to occasionally override the behavior to render titles, but otherwise use the base class implementation for rendering checkboxes. In my opinion, this issue is a bug in the CheckBoxList class since you should not be forced to use the base method if the class is truly virtual. I haven't bothered to report this to Microsoft - feel free to let them know about it!

The simplest solution that I could think of was to execute the base class' RenderItem method, but don't let it output any HTML to the Web Form. This is where the dummyWriter comes in to play; the base class does its work on the first ListItem and outputs HTML to the dummyWriter which never gets used for anything.

Taking it Further...

Rendering horizontally

For the moment, the TitleCheckBoxList is doing exactly what I need, so I have not added any other feature or tried any other variations on the output. Your needs will certainly vary, and you should feel free to experiment with it even further. Maybe you will want to render the checkboxes in rows rather than columns, this doesn't seem like it would be too difficult to accomplish. I would approach it by setting the RepeatDirection to "Horizontal" and then setting the RepeatColumns property to the maximum number of ListItems that you want displayed on a row. There might be some tricky code when you load the TitleCheckBoxList so that you insert spacers and the row titles in the correct spots, but it should be possible.

Inserting other controls or content into a CheckBoxList

Is there any reason why we can't insert other types of controls into the CheckBoxList? I needed to get a title into the CheckBoxList, but maybe you want to insert a Button or an Image. Can this be done? Absolutely! If you follow the example of how to render a Label control in the TitleCheckBoxList's RenderItem method, you can basically render any kind of control in place of a ListItem.

Conclusion

The .NET Framework and ASP.NET makes it really easy to modify and extend the functionality of the classes and controls. All you need is a little bit of knowledge of how the framework is built and how the components interact with each other.

By extending the CheckBoxList class with less than 70 lines of code, I was able to get the exact functionality that I was looking for. So, if the built-in controls are not doing what you want, don't give up on them, change the way they work to suit your needs better!

License

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


Written By
Web Developer
United States United States
Professional software developer with a track record of delivering reliable production web applications.
Specializing in modern web application development with Azure, AWS, C#, .NET, NodeJs, Web API, REST, SQL Server, JavaScript, ReactJs, jQuery, Bootstrap, and CSS.

Comments and Discussions

 
QuestionHow can i create the control (TitleCheckboxlist) from code behind Pin
Member 145631544-Sep-19 18:11
Member 145631544-Sep-19 18:11 
QuestionNice one Pin
Member 1338498229-Aug-17 21:08
Member 1338498229-Aug-17 21:08 
GeneralMy vote of 5 Pin
john_avis31-Oct-12 14:37
john_avis31-Oct-12 14:37 
Questioncan VWDCMS:titlecheckboxlist sub categories accessed in javascript [modified] Pin
NazishAbbasi10-Feb-10 23:26
NazishAbbasi10-Feb-10 23:26 
AnswerRe: can VWDCMS:titlecheckboxlist sub categories accessed in javascript Pin
Jeff Bazinet11-Feb-10 7:07
Jeff Bazinet11-Feb-10 7:07 
GeneralRe: can VWDCMS:titlecheckboxlist sub categories accessed in javascript Pin
NazishAbbasi11-Feb-10 18:18
NazishAbbasi11-Feb-10 18:18 
Questioncheckbox list with titles for winforms? Pin
drpaul0927-Sep-09 4:29
drpaul0927-Sep-09 4:29 
GeneralI tried checkboxlist with Images but on postback its loosing state Pin
Rashmi_developer4-Sep-09 1:12
Rashmi_developer4-Sep-09 1:12 
Generalat last... Pin
ElBrunzy27-Nov-08 7:05
ElBrunzy27-Nov-08 7:05 
QuestionHow to use it with a RadioButtonList? Pin
ETollenaar2-Oct-08 3:31
ETollenaar2-Oct-08 3:31 
AnswerRe: How to use it with a RadioButtonList? Pin
Jeff Bazinet2-Oct-08 5:04
Jeff Bazinet2-Oct-08 5:04 
GeneralRe: How to use it with a RadioButtonList? Pin
ETollenaar2-Oct-08 5:08
ETollenaar2-Oct-08 5:08 
GeneralRe: How to use it with a RadioButtonList? Pin
ETollenaar2-Oct-08 20:21
ETollenaar2-Oct-08 20:21 
GeneralRe: How to use it with a RadioButtonList? Pin
nicuzzo19-Nov-08 1:07
nicuzzo19-Nov-08 1:07 
AnswerRe: How to use it with a RadioButtonList? Pin
Jeff Bazinet19-Nov-08 19:17
Jeff Bazinet19-Nov-08 19:17 
GeneralCheckBoxList with Hyperlink text Pin
ken_in_oz3-Jul-08 18:52
ken_in_oz3-Jul-08 18:52 
Hi:

The post is great! Thanks for sharing. I am interesting to see if you can create a CheckBoxList with Hyperlink Text. On the example you create a Label, I can replace it with a Hyperlink Label, but how could I add a checkbox on that still has repeater function?

MCSD

GeneralRe: CheckBoxList with Hyperlink text Pin
Jeff Bazinet3-Jul-08 20:03
Jeff Bazinet3-Jul-08 20:03 
QuestionCheckboxlist with title, but in a different layout Pin
aneel_124-Apr-08 6:05
aneel_124-Apr-08 6:05 
GeneralRe: Checkboxlist with title, but in a different layout Pin
Jeff Bazinet7-Apr-08 17:01
Jeff Bazinet7-Apr-08 17:01 
GeneralRe: Checkboxlist with title, but in a different layout Pin
aneel_128-Apr-08 4:04
aneel_128-Apr-08 4:04 
GeneralThis was awesome AND just what I was looking for Pin
hangtendesign2-Apr-08 9:55
hangtendesign2-Apr-08 9:55 
GeneralRe: This was awesome AND just what I was looking for Pin
Jeff Bazinet2-Apr-08 17:04
Jeff Bazinet2-Apr-08 17:04 
QuestionDynamically Added items Pin
Lee C Baker22-Aug-07 20:47
Lee C Baker22-Aug-07 20:47 
AnswerRe: Dynamically Added items Pin
Jeff Bazinet10-Sep-07 22:29
Jeff Bazinet10-Sep-07 22:29 

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.