Introduction

The CheckBoxList, like most other web controls, makes my life a whole lot easier by automating what used to be a lot of drudge work. The CheckBoxList also, like most other web controls, spits out ugly, ugly markup that makes me incredibly pissed off. But the good thing in ASP .NET is that if you don’t like the way something works, you can almost always inherit from the class and override the behavior, which is what we’re going to be doing with CheckBoxList.

Web Custom Controls vs. User Controls

Web custom controls have several benefits over user controls. To use a user control, you need to copy the .ascx file to each and every project that you you want to use it in, whereas web controls are compiled into .dll files, which means that to use them you just add a reference to the .dll file. There’s also the fact that user controls don’t have designer support (admittedly not a big deal for me, since I work almost exclusively in the “Source View,” but I know lots of other people swear by the “Design View”); web custom controls, on the other hand, do.

Web Custom Controls

Creating web custom controls can look like an untamable beast, but actually it’s quite easy. Start by clicking File » New » Project » Visual C# » Windows » Web Control Library. You can just as easily create a web custom control in whatever web project you happen to be working on, but because we’re interested in easy reuse, we’ll put our extended CheckBoxList file in a web control library. Name it whatever you want.

Visual Studio will automatically create a file called WebCustomControl1.cs for you. Delete everything inside the class — we don’t need it. Rename the file to something more appropriate, like UlCheckBoxList, and change all instances of WebCustomControl1 in the file to UlCheckBoxList (Visual Studio will probably automatically change the class name for you, but you also need to change the ToolboxData).

Base Class

All web custom controls need to inherit from the WebControl class either directly or indirectly. The CheckBoxList control already inherits from this class. Since we’re interested in only the rendering part of the CheckBoxList we’ll inherit from this one.

The Code

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Text;
  5. using System.Web;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8.  
  9. namespace XhtmlWebControls
  10. {
  11. [ToolboxData("<{0}:UlCheckBoxList runat=server></{0}:UlCheckBoxList>")]
  12. public class UlCheckBoxList : CheckBoxList
  13. {
  14. protected override void Render(HtmlTextWriter writer)
  15. {
  16. Controls.Clear();
  17.  
  18. string input = "<input id={0}{1}{0} name={0}{2}{0} type={0}checkbox{0} value={0}{3}{0}{4} />";
  19. string label = "<label for={0}{1}{0}>{2}</label>";
  20.  
  21. writer.WriteLine("<ul>");
  22.  
  23. for (int index = 0; index < Items.Count; index++)
  24. {
  25. writer.Indent++;
  26. writer.Indent++;
  27.  
  28. writer.WriteLine("<li>");
  29.  
  30. writer.Indent++;
  31.  
  32. StringBuilder sbInput = new StringBuilder();
  33. StringBuilder sbLabel = new StringBuilder();
  34.  
  35. sbInput.AppendFormat(
  36. input,
  37. """,
  38. base.ClientID + "_" + index.ToString(),
  39. base.ClientID + "$" + index.ToString(),
  40. Items[index].Value,
  41. (Items[index].Selected ? " checked" : ""));
  42.  
  43. sbLabel.AppendFormat(
  44. label,
  45. """,
  46. base.ClientID + "_" + i.ToString(),
  47. Items[index].Text);
  48.  
  49.  
  50. writer.WriteLine(sbInput.ToString());
  51. writer.WriteLine(sbLabel.ToString());
  52.  
  53. writer.Indent–;
  54.  
  55. writer.WriteLine("</li>");
  56.  
  57. writer.WriteLine();
  58.  
  59. writer.Indent–;
  60. writer.Indent–;
  61. }
  62.  
  63. writer.WriteLine("</ul>");
  64. }
  65. }
  66. }
  67.  

Explained

Line 11: [ToolboxData("<{0}:UlCheckBoxList runat=server></{0}:UlCheckBoxList>")]

This tells Visual Studio what to write in the “Source View” of the .aspx page in which we’re going to use the control. That is, if you drag and drop the control from the Toolbox onto the .aspx page.

Line 16: Controls.Clear(); The CheckBoxList has a single child control of type CheckBox, which is used to render all the checkboxes in the list. But as we’re going to be writing the HTML ourselves, we don’t care about this control. So I cleared it, just in case having it around screws up something.

Line 18: string input = “<input id={0}{1}{0} name={0}{2}{0} type={0}checkbox{0} value={0}{3}{0}{4} />”;

Line 19: string label = “<label for={0}{1}{0}>{2}</label>”;

The html that’s going to be outputted with some “string format variables” thrown in. The formats are going to be replaced with the actual values later on (lines 35 - 47).

Line 25: writer.Indent++;

Makes the <li> tags and everything underneath appear one tab to the right (in the HTML source code) of the <ul> tag.

Line 38: base.ClientID + “_” + i.ToString(),

Line 39: base.ClientID + “$” + i.ToString(),

If your CheckBoxList’s name was “CheckBoxList1,” then the id and the name you see in the HTML source code would be “CheckBoxList1_x” and “CheckBoxList1$x,” where x is the number of the checkbox in the list. I saw no reason to change this.

Adding Our Class to the Toolbox

Compile the Web Control Library you just created. Go to the Toolbox, right-click on “General” (or whichever tab you want to put the class under) and select “Choose Items” — In “Choose Toolbox Items,” under “.NET Framework Components,” select “Browse” and point to the .dll file of the class (should be located in the “Debug” folder in the “Bin” folder of your Web Control Library folder). Click OK. And you’re good to go.