5,448,104 members and growing! (16,805 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, C#), Javascript, CSS, HTML, XHTML, .NET (.NET, .NET 2.0), ASP, ASP.NET, Ajax, Dev

Posted: 27 Jun 2008
Updated: 27 Jun 2008
Views: 2,817
Bookmarked: 7 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
1 vote for this Article.
Popularity: 0.00 Rating: 3.00 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
1 vote, 100.0%
3
0 votes, 0.0%
4
0 votes, 0.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

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



Occupation: Web Developer
Location: South Africa South Africa

Other popular ASP.NET articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
  (Refresh) 
Subject  Author Date 
-- 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-2008
Web18 | Advertise on the Code Project