by Robert C. Barth First Posted May 22, 2008

A lot of software has hierarchies in it. Anything having to do with classifications, ordering, or reporting structures usually has some kind of hierarchy involved. Many times, a tree control is an easy and convenient way to show the hierarchy. It has nice little plus and minus signs as well as little tree "branch" lines linking the parent elements to the child elements.

However, sometimes a tree control is overkill. For instance, if you are adding functionality to permit the user to search through some records via a field that is a hierarchy, you don't really need to show a whole tree control. A drop-down list with indented items would most likely fit the bill, especially if the hierarchy doesn't have too many items.

Filling a drop-down list with hierarchical items is rather trivial when you think about it. As long as you know the hierarchy level of an item, and the items are given to you in order of the hierarchy, you can simply indent by the hierarchy level (e.g. if you have an element that is a first order ancestor of the root, indent by one space, two order ancestor, indent by two spaces, etc.).

To make this work, since user agents (browsers) automatically distill extra space in HTML (as they should, according to the HTML spec), you need to use the HTML character entity   to add your extra spaces. In .net, however, there is a problem: the DropDownList control does not render HTML character entities in the ListItem text property. The implementation for the ListControl's RenderContents method (DropDownList is derived from ListControl) uses the HttpUtility class's HtmlEncode method when writing out the ListItem's text. This makes any attempt at adding an HTML character entity futile. What's a developer to do? Well, you can derive a new control from DropDownList and override the RenderContents method yourself:

   1: using System;
   2: using System.Web.UI.WebControls;
   3:  
   4: namespace Norimek.Web.UI.WebControls
   5: {
   6:     public class UnEncodedDropDownList : DropDownList
   7:     {
   8:  
   9:         protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
  10:         {
  11:             ListItemCollection items = this.Items;
  12:  
  13:             for (int i = 0; i < items.Count; i++)
  14:             {
  15:                 ListItem item = items[i];
  16:  
  17:                 if (item.Enabled)
  18:                 {
  19:                     writer.WriteBeginTag("option");
  20:  
  21:                     if (item.Selected)
  22:                         writer.WriteAttribute("selected", "selected");
  23:  
  24:                     writer.WriteAttribute("value", item.Value, false);
  25:  
  26:                     if (item.Attributes != null && item.Attributes.Count > 0)
  27:                         item.Attributes.Render(writer);
  28:  
  29:                     if (this.Page != null)
  30:                         this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
  31:  
  32:                     writer.Write('>');
  33:  
  34:                     writer.Write(item.Text);
  35:  
  36:                     writer.WriteEndTag("option");
  37:                     writer.WriteLine();
  38:                 }
  39:             }
  40:         }
  41:     }
  42: }

The important part is line 34. Where it previously was HttpUtility.HtmlEncode(item.Text, writer), it is now just plain writer.Write(item.Text). Just use this control in place of a regular DropDownList control anytime you need to display a hierarchical list (or need to use HTML character entities in drop-down). I leave the creation of the controls item collection as an exercise for the reader since it will be highly-individualized. Suffice it to say it will very likely involve a small recursive function.

Of course you know, with great power comes great responsibility. Microsoft encoded that value for a reason. A lot of the time that text value is something the user entered. A malicious user could enter all sorts of crazy stuff into whatever data is later displayed on the page via this new control and wreak havoc with your application. It is your responsibility to make sure that the data that is in that text property is not something that will harm your user or the website, or anything else for that matter.

Next time I will show you how to implement a derived DropDownList that gives you the ability to use the <optgroup> tag inside of it so you can group your option items. Not terribly important, but very convenient when needed. And, surprisingly, a little bit more complicated than it seems it would be when you first look at it.

Tags: , , , , ,

ASP.net Server Controls | Programming | UI Controls

blog comments powered by Disqus

Powered by BlogEngine.NET 2.5.0.10

Site LogoCopyright © 2012 Robert C. Barth. All Rights Reserved.

 
 

Bio

This is the blog of Robert C. Barth dedicated to software engineering and (mostly) related things. Robert has over seventeen years of experience engineering software solutions, from architecture to design, development, requirements gathering, technical writing, and UI design. He lives in Chandler, Arizona and when he is not working on software projects you can probably find him riding his Honda CBR1000RR around the south east valley.