Click here to Skip to main content
6,306,412 members and growing! (23,567 online)
Email Password   helpLost your password?
Web Development » ASP.NET » Howto     Intermediate License: The Code Project Open License (CPOL)

Create CheckBox Option groups

By Riaan Lehmkuhl

How to... Create CheckBox Option groups
C# (C# 2.0), Javascript, CSS, HTML, XHTML, .NET (.NET 2.0), ASP, ASP.NET, WebForms, Ajax, Dev
Posted:27 Jun 2008
Views:6,927
Bookmarked:9 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
1 vote for this article.
Popularity: 0.00 Rating: 3.00 out of 5

1

2
1 vote, 100.0%
3

4

5

Introduction

I was recently given a website to make changes on. The HTML was already done and signed off by the client, and could thus not be changed.
Then I came across a bunch of options that needed to be saved to the db and instead of using RadioButtonList controls, there was a table containing a lot of CheckBox controls.
To simulate the RadioButtonList behaviour for the CheckBox groups, one could use AutoPostBack and a bunch of if statements. Also don't forget all the db access code that has to be written to save the selections to the database.
This would lead to a horrible UI, and difficult to maintain back end.

My Solution

The first thing to do is to make the HTML Table accessible by adding an Id and the "runat='server'" attribute. Now we can transverse the table, and access it's child controls from the CodeBehind.
The next issue is to divide the CheckBox controls into groups. This can be easily achieved by adding a "group" attribute to each CheckBox.

<asp:CheckBox group="1" ID="CheckBox1" runat="server" Text="Option 1" />

Now we can look at the server side code:
Using a Recursive FindControls method, we can get a list of the CheckBox controls in the Table.

/// <summary>
/// Recursively find a set of controls in a container
/// </summary>

/// <param name="type">The type of control to find.</param>
/// <param name="container">The container to search in.</param>
/// <param name="controls">The list of found controls</param>
private void FindControls(Type type, Control container, ref System.Collections.Generic.List<Control> controls) {
    foreach (Control c in container.Controls) {
        if (c.GetType() == type) controls.Add(c);
        FindControls(type, c, ref controls);
    }
}

Now when the page loads we can get a list of the CheckBox controls and add some JavaScript to them to simulate the RadioButtonList behaviour.

System.Collections.Generic.List<Control> controls = new System.Collections.Generic.List<Control&lg;(); // List of the checkboxes
FindControls(typeof(CheckBox), tblOptions, ref controls); // get the checkboxes

// a list of the checkbox groups and their related checkboxes to help with js generation.
System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<CheckBox>> chkGroups = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<CheckBox>>();

// get the controls
foreach (Control c in controls) {
    CheckBox chk = (c as CheckBox);

    // build the checkbox group list
    if (null != chk.Attributes["group"] && string.Empty != chk.Attributes["group"]) {
        if (chkGroups.ContainsKey(chk.Attributes["group"])) {
            chkGroups[chk.Attributes["group"]].Add(chk);
        } else {
            chkGroups.Add(chk.Attributes["group"], new System.Collections.Generic.List<CheckBox>());
            chkGroups[chk.Attributes["group"]].Add(chk);
        }
    }
}

// generate the checkbox js to simmulate option groups
foreach (string k in chkGroups.Keys) {
    foreach (CheckBox cb in chkGroups[k]) {
        string js = "javascript:if(this.checked){";
        foreach (CheckBox cb2 in chkGroups[k]) {
            if (cb.ID == cb2.ID) continue;
            js += "document.getElementById('" + cb2.ClientID + "').checked=false;";
        }
        js += "};";
        cb.Attributes.Add("onclick", js);
    }
}

Try out the result: CheckBoxOptionGroups_demo.zip (extract and open CheckBoxOptionGroups.html)

Following that wonderful philosophy "Less is More", I've decided to store all the selections in just one field in the db using Flags. In this example we'll just use a Cookie.
Again by using a custom HTML attribute to set the Flag value of each CheckBox. The values are set like Bit Flag Enums (eg. 1,2,4,8,16,etc.).

<asp:CheckBox bit="1" group="1" ID="CheckBox1" runat="server" Text="Option 1" />

Now when the user has made his selection, we can check for the checked CheckBox controls and add up their Flag values.

private void UpdateOptionFlags() {
    long optionFlags = 0;
    System.Collections.Generic.List<Control> controls = new System.Collections.Generic.List<Control>(); // List of the checkboxes
    FindControls(typeof(CheckBox), tblOptions, ref controls); // get the checkboxes

    // iterate the list of checkboxes and get the set flags
    foreach (Control c in controls) {
        CheckBox chk = (c as CheckBox);
        if (null == chk.Attributes["bit"]) continue; //if not one of the flag checkboxes try the next one.
        long bit = 0;
        if (!long.TryParse(chk.Attributes["bit"], out bit)) continue; //if no workable flag try the next one.
        if (chk.Checked) optionFlags += bit;
    }

    // Set selected options value
    Response.Cookies.Clear();
    Response.Cookies.Add(new HttpCookie("OptionFlags", Convert.ToString(optionFlags)));
}

All that's left now is to read the selected flags and set the checked value of the relevant CheckBox controls. Here is the completed method to simulate the RadioButtonList behaviour and to read the selected values.

private void LoadOptionFlags() {
    System.Collections.Generic.List<Control> controls = new System.Collections.Generic.List<Control&lg;(); // List of the checkboxes
    FindControls(typeof(CheckBox), tblOptions, ref controls); // get the checkboxes
    
    // a list of the checkbox groups and their related checkboxes to help with js generation.
    System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<CheckBox>> chkGroups = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<CheckBox>>();
    
    // get the controls
    foreach (Control c in controls) {
        CheckBox chk = (c as CheckBox);
        
        CheckBox chk = (c as CheckBox);
        if (null == chk.Attributes["bit"]) continue; //if not one of the flag checkboxes try the next one.
        long bit = 0;
        if (!long.TryParse(chk.Attributes["bit"], out bit)) continue; //if no workable bit try the next one.
    
        // check to see if the bit was set
        chk.Checked = ((bit & optionFlags) != 0);
    
        // build the checkbox group list
        if (null != chk.Attributes["group"] && string.Empty != chk.Attributes["group"]) {
            if (chkGroups.ContainsKey(chk.Attributes["group"])) {
                chkGroups[chk.Attributes["group"]].Add(chk);
            } else {
                chkGroups.Add(chk.Attributes["group"], new System.Collections.Generic.List());
                chkGroups[chk.Attributes["group"]].Add(chk);
            }
        }
    }
    
    // generate the checkbox js to simmulate option groups
    foreach (string k in chkGroups.Keys) {
        foreach (CheckBox cb in chkGroups[k]) {
            string js = "javascript:if(this.checked){";
            foreach (CheckBox cb2 in chkGroups[k]) {
                if (cb.ID == cb2.ID) continue;
                js += "document.getElementById('" + cb2.ClientID + "').checked=false;";
            }
            js += "};";
            cb.Attributes.Add("onclick", js);
        }
    }
}

Using the Code

Just extract to a local directory, open the website with Visual Studio 2005/2008 and run.

History

28 June 2008

  • Original article posted

License

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

About the Author

Riaan Lehmkuhl


Member

Occupation: Web Developer
Location: South Africa South Africa

Other popular ASP.NET articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
  (Refresh) 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 27 Jun 2008
Editor:
Copyright 2008 by Riaan Lehmkuhl
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project