![]() |
Web Development »
ASP.NET »
Howto
Intermediate
License: The Code Project Open License (CPOL)
Create CheckBox Option groupsBy Riaan LehmkuhlHow to... Create CheckBox Option groups |
C# (C# 2.0), Javascript, CSS, HTML, XHTML, .NET (.NET 2.0), ASP, ASP.NET, WebForms, Ajax, Dev
|
||||||||
|
Advanced Search |
|
|
|
||||||||||||||||
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.
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≶(); // 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≶(); // 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);
}
}
}
Just extract to a local directory, open the website with Visual Studio 2005/2008 and run.
28 June 2008
General
News
Question
Answer
Joke
Rant
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 |