Click here to Skip to main content
15,886,258 members
Articles / Web Development / ASP.NET
Article

ASP.NET DropDownList with OptionGroup support

Rate me:
Please Sign up or sign in to vote.
4.81/5 (39 votes)
12 Sep 20061 min read 485.9K   8.7K   108   100
An implementation of a DropDownList Control Adapter which provides OptionGroup support.

Introduction

ASP.NET 2.0, for all its bells and whistles, lacks the odd bit of functionality for reasons completely unknown. One such notable omission is that of OptionGroup (<optgroup>) support in the DropDownList control. For those unfamiliar with the <optgroup> element, it is part of the XHTML standard, and has the effect of categorising items in a <select>, as the following image shows.

Option Groups

When I first began to look for a solution to implement this in ASP.NET, I found very few articles on the topic that offered any viable solution. Another CodeProject member came up with a nice clean solution, but it looked like a lot of code and I was convinced there was an easier way. After reading some comments, it became apparent a Control Adapter was the way to go. Control Adapters are new in ASP.NET 2.0, and allow the developer to override the rendering behaviour of any control, very powerful stuff! Furthermore, Control Adapters are used in conjunction with a browser file, so specific browsers may be targeted, if required. Armed with that knowledge, the solution became simple. The attached download contains the requisite files to implement this solution in your own projects, but for posterity, I paste it here also.

C#
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();
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: Other browsers Pin
lotuspro19-Oct-06 4:07
lotuspro19-Oct-06 4:07 
GeneralRe: Other browsers Pin
scott091215-Feb-07 4:55
scott091215-Feb-07 4:55 
AnswerRe: Other browsers Pin
lotuspro15-Feb-07 5:17
lotuspro15-Feb-07 5:17 
GeneralRe: Other browsers Pin
jnovax3-Jul-07 23:31
jnovax3-Jul-07 23:31 
QuestionenableEventValidation in PostBack ? Pin
itzikbs19-Sep-06 23:53
itzikbs19-Sep-06 23:53 
AnswerRe: enableEventValidation in PostBack ? [modified] Pin
Thxman25-Sep-06 3:16
Thxman25-Sep-06 3:16 
GeneralRe: enableEventValidation in PostBack ? Pin
lotuspro25-Sep-06 22:18
lotuspro25-Sep-06 22:18 
GeneralRe: enableEventValidation in PostBack ? Pin
Thxman27-Sep-06 2:23
Thxman27-Sep-06 2:23 
By the way, I have noticed another thing :
when you look at the html source, you can see that the 'optiongroup'
attribute and his value is propagated to all 'option' tags.

Since the 'option' tag hasn't such attribute, why do youattach it ?

So I removed those attributes by commenting the foreach loop in the RenderListItem method :
[...]
        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);
[...].

It works as well and the page is validated by Tidy.

Last thing : in the browserfile, you can replace refID="IE6to9" by refID="Default"
to make this nice control works with all browsers
(I'm only using Firefox on my windows and linux boxes, noone's perfect !! Poke tongue | ;-P ).

Anyway, thanks lotuspro for the original code.
It's really nicer when using long list of choices.

Thxman
PS: just too say I'm french, so excuse my english ...
GeneralRe: enableEventValidation in PostBack ? Pin
wuxsh6-Sep-07 20:31
wuxsh6-Sep-07 20:31 
GeneralRe: enableEventValidation in PostBack ? Pin
Pawel Krakowiak26-Sep-07 0:26
Pawel Krakowiak26-Sep-07 0:26 
Questionoptgroup structure disappears after PostBack Pin
oudoulj13-Sep-06 23:25
oudoulj13-Sep-06 23:25 
AnswerRe: optgroup structure disappears after PostBack Pin
lotuspro14-Sep-06 0:28
lotuspro14-Sep-06 0:28 
AnswerRe: optgroup structure disappears after PostBack Pin
oudoulj14-Sep-06 2:08
oudoulj14-Sep-06 2:08 
GeneralRe: optgroup structure disappears after PostBack Pin
lotuspro14-Sep-06 2:22
lotuspro14-Sep-06 2:22 
GeneralRe: optgroup structure disappears after PostBack Pin
mick_lennon31-Oct-06 0:37
mick_lennon31-Oct-06 0:37 
QuestionRe: optgroup structure disappears after PostBack Pin
udowe2-Nov-06 3:12
udowe2-Nov-06 3:12 
AnswerRe: optgroup structure disappears after PostBack Pin
Albert Weinert12-Nov-06 12:17
Albert Weinert12-Nov-06 12:17 
GeneralRe: optgroup structure disappears after PostBack Pin
lukejackson1-Mar-07 1:29
lukejackson1-Mar-07 1:29 
GeneralRe: optgroup structure disappears after PostBack Pin
jmaronge23-May-07 18:07
jmaronge23-May-07 18:07 
GeneralRe: optgroup structure disappears after PostBack Pin
Illya Kozachenko18-Jun-07 22:57
Illya Kozachenko18-Jun-07 22:57 
GeneralRe: optgroup structure disappears after PostBack Pin
lukejackson19-Jun-07 2:15
lukejackson19-Jun-07 2:15 
GeneralRe: optgroup structure disappears after PostBack Pin
GooglizedCoder13-Jul-07 10:56
GooglizedCoder13-Jul-07 10:56 
GeneralRe: optgroup structure disappears after PostBack Pin
xsoftdev18-Jul-07 12:23
xsoftdev18-Jul-07 12:23 
AnswerRe: optgroup structure disappears after PostBack Pin
JunioraTm18-Apr-10 10:39
JunioraTm18-Apr-10 10:39 
GeneralRe: optgroup structure disappears after PostBack Pin
brenjt6-Oct-11 12:05
brenjt6-Oct-11 12:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.