Craig Gibbons' Lifeblog lifeblog://tri.eat.net

23Aug/060

ASP.NET DropDownList with OPTGROUP support

One of the new tags in the XHTML standard is OPTGROUP. This long
missing tag provides the ability to group elements into sub-sections
inside a SELECT element. Unfortunately, the ASP.NET DropDownList server
control lacks the ability to add OPTGROUP’s to its items collection, so
it falls to the developer to provide a custom solution for this. I did
some looking around and found a few solutions to the problem, but none
of them really looked like the real deal, until I discovered Control
Adapters in .NET 2.0! Essentially, Control Adapters allow you to
override any method of a control by providing your own implementation.
Even better still, you can use this technology to target different
browsers in different ways by using a browser file. From there, the
solution was quite simple. The steps and associated code are as follows:

  1. Create a .browser file. Paste in the following code:

    <browsers>

      <browser refID="IE6to9">

        <controlAdapters>

          <adapter controlType="System.Web.UI.WebControls.DropDownList"

          adapterType="DropDownListAdapter" />

        </controlAdapters>

      </browser>

    </browsers>

  2. Create a file called DropDownListAdapter.cs in App_Code or a sub
    directory thereof (I use a folder called Adapters), paste in the
    following code:
    public class DropDownListAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter {
        protected override void RenderContents(HtmlTextWriter writer) {
            DropDownList list = this.Control as DropDownList;

            string currentOptionGroup;
            List<string> renderedOptionGroups = new List<string>();

            foreach(ListItem item in list.Items) {
                if(item.Attributes["OptionGroup"] == null) {
                    RenderListItem(item, writer);
                } else {
                   
    currentOptionGroup = item.Attributes["OptionGroup"];

                   
    if(renderedOptionGroups.Contains(currentOptionGroup)) {
                       
    RenderListItem(item, writer);
                    } else {
                       
    if(renderedOptionGroups.Count > 0) {
                           
    RenderOptionGroupEndTag(writer);
                        }

                       
    RenderOptionGroupBeginTag(currentOptionGroup, writer);
                       
    renderedOptionGroups.Add(currentOptionGroup);

                       
    RenderListItem(item, writer);
                    }
                }
            }

            if(renderedOptionGroups.Count > 0) {
                RenderOptionGroupEndTag(writer);
            }
        }

        private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer) {
            writer.WriteBeginTag("optgroup");
            writer.WriteAttribute("label", name);
            writer.Write(HtmlTextWriter.TagRightChar);
            writer.WriteLine();
        }

        private void RenderOptionGroupEndTag(HtmlTextWriter writer) {
            writer.WriteEndTag("optgroup");
            writer.WriteLine();
        }

        private void RenderListItem(ListItem item, HtmlTextWriter writer) {
            writer.WriteBeginTag("option");
            writer.WriteAttribute("value", item.Value, true);

            if(item.Selected) {
                writer.WriteAttribute("selected", "selected", false);
            }

            foreach(string key in item.Attributes.Keys) {
                writer.WriteAttribute(key, item.Attributes[key]);
            }

            writer.Write(HtmlTextWriter.TagRightChar);
            HttpUtility.HtmlEncode(item.Text, writer);
            writer.WriteEndTag("option");
            writer.WriteLine();
        }
    }

From there, usage of the DropDownList is exactly the same, except you
need to add an OptionGroup attribute to any items you wish to add to a
given group, sample code as follows:

ListItem item1 = new ListItem(“South Africa”, “SA”);
ListItem item2 = new ListItem(“United States”, “US”);
ListItem item3 = new ListItem(“United Kingdom”, “UK”);
item1.Attributes[“OptionGroup”] = “Countries”;
item1.Attributes[“OptionGroup”] = “Countries”;
item1.Attributes[“OptionGroup”] = “Countries”;

ddlCountries.Items.Add(item1);
ddlCountries.Items.Add(item2);
ddlCountries.Items.Add(item3);

Filed under: Tech Leave a comment
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.