Aspx CheckBoxList Alternative that allows for the OnCheckedChanged event
My team had to edit an older apsx website and add a list of CheckBoxes, which are actually html <input type="checkbox"/>
tags. We assumed that CheckBoxList
would be perfect for our task. We assumed wrong.
I wrote desktop apps for years and now that I am writing web apps, I am using MVC and Razor, so I missed the aspx days. However, having to work on legacy aspx applications is catching me up.
My use case for list of CheckBoxes
Really, my use case is simple. There are icons that should show up for some products. We wanted to store a map between products and the icons in the database. On the product page, we want a list of the icons with a checkbox by each list item. This would allow the person who creates new products to select which icons to show on a product download page.
- Get a list of option from a database and display that list as html checkboxes.
- Checking a checkbox should add a row to a database table.
- Unchecking a checkbox should remove that row from a database table.
CheckBoxList Fails
So what I needed was an OnClick event which is actually called OnCheckedChanged
in an asp:Checkbox
. Well, it turns out that the CheckBoxList
control doesn’t support the OnCheckedChanged
event per CheckBox. The CheckBoxList doesn’t have any type of OnClick method. Instead, there is an OnSelectedIndexChanged
event. But OnSelectedIndexChanged
doesn’t even tell you which CheckBox was clicked. If a CheckBox
is checked, then in the OnSelectedIndexChanged
event, the SelectedItem
equals the clicked item, however, if the CheckBox
is unchecked, the SelectedItem
was a completely different CheckBox
that is checked.
So to me, this made the CheckBoxList
control not usable. So I set out to replicate a CheckBoxList
in a way that supports OnCheckedChanged
.
Repeater with CheckBox for ItemTemplate
I ended up using the Repeater
control with an ItemTemplate
containing a CheckBox
. Using this method worked pretty much flawlessly. It leaves me to wonder, why was CheckBoxList
created in the first place if a Repeater
with a CheckBox
in the template works perfectly well.
Here is my code:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CheckBoxListExample._Default" %> <%@ Import Namespace="CheckBoxListExample" %> <%@ Import Namespace="CheckBoxListExample.Models" %> <asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> <div> <asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <asp:CheckBox ID="cb1" runat="server" AutoPostBack="true" OnCheckedChanged="RepeaterCheckBoxChanged" Text="<%# ((CheckBoxViewModel)Container.DataItem).Name %>" Checked="<%# ((CheckBoxViewModel)Container.DataItem).IsChecked %>" /> </ItemTemplate> </asp:Repeater> </div> </asp:Content>
using System; using System.Collections.Generic; using System.Web.UI; using System.Web.UI.WebControls; using CheckBoxListExample.Models; namespace CheckBoxListExample { public partial class _Default : Page { private List<CheckBoxViewModel> _ViewModels; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { var _ViewModels = new List<CheckBoxViewModel> { new CheckBoxViewModel {Name = "Test1", IsChecked = true}, new CheckBoxViewModel {Name = "Test2"}, new CheckBoxViewModel {Name = "Test3"} }; Repeater1.DataSource = _ViewModels; Repeater1.DataBind(); } } protected void RepeaterCheckBoxChanged(object sender, EventArgs e) { var cb = sender as CheckBox; if (cb == null) return; if (cb.Checked) { // Insert } else { // Delete } } } }
namespace CheckBoxListExample.Models { public class CheckBoxViewModel { public string Name { get; set; } public bool IsChecked { get; set; } } }