Click here to Skip to main content
12,889,105 members (51,893 online)
Click here to Skip to main content
Add your own
alternative version


103 bookmarked
Posted 11 Jul 2004

ASP.NET Color DropDown Control

, 27 Jan 2005 CPOL
Rate this:
Please Sign up or sign in to vote.
An example of persisting and parsing a custom collection in an ASP.NET server control.


When developing controls for a designer environment like Visual Studio or WebMatrix, the complexities of persisting control properties as serialized HTML can come into play. In many cases, the built-in serialization of control properties as attributes or nested child tags is sufficient. There are also several code attributes available to a control developer to apply a degree of customization for this process. In some cases however, a developer requires a greater degree of control over how control properties are persisted as HTML.

In this article, I present a custom ASP.NET server control for displaying color choices in a dropdown list. Following a description of the control, I will focus on the problem of persisting a custom collection of items in the context of the Visual Studio Web Form designer, and offer a solution using custom ControlDesigner and ControlBuilder objects.

HtmlColorDropDown Control

The HtmlColorDropDown web control encapsulates an HTML dropdown list (i.e., <select> tag) with colors for items (<option> tags). The control can render the items themselves as foreground or background colors within the <option> tags. The choice of colors offered is determined by the value of the Palette property, which can be one of the following:


All named colors (not including System colors) available in the System.Drawing.KnownColor enumeration.


A small subset of common named colors.


The 216 colors considered "web-safe"; these use only hex values #FF, #CC, #99, #66, #33, and #00 for each of the red, green, and blue components.


Colors identified by the control user through the UserDefinedColors property.

The UserDefinedColors property is a ColorCollection object. ColorCollection is a strongly-typed collection class inheriting from CollectionBase, using standard System.Drawing.Color objects for items.

The DisplayColorMode property governs how colors will be displayed in each item, if at all:


Display each item using its color for the background; foreground text is displayed in either black or white, depending on which offers a better contrast.


Display each item using its color for the foreground text.


Do not display colors in the items.

The selected item is available as a Color object through the SelectedColor property. The properties SelectedColorName and SelectedColorHexString return the name of the selected color (for named colors) and the HTML hex value (e.g., "#FFC309") as strings respectively. These are all read/write properties; the setting of one affects the value of all three. If an attempt is made to set the SelectedColor to a color that doesn't exist in the current Palette, a value of Color.Empty is assigned instead. Likewise, if the Palette is changed, SelectedColor may be set to Color.Empty if its existing value isn't among the new list of choices.

Note that the proper display of foreground or background colors rendered in <option> tags is dependent on the browser. Most modern browsers interpret item colors identified as CSS properties through a style attribute, without problems. Interestingly however, not all render the colors of the selected item when the dropdown is collapsed. To work around this, the AutoColorChangeSupport property is provided. When true (its default value), a small JavaScript onChange handler is rendered with the control, causing the colors of the selected item to be assigned to the parent <select> tag. The property may be set to false to prevent this behavior.

The default event for the control is ColorChanged. This event fires whenever the selection in the dropdown list has changed between postbacks to the server. The following is an example of an .aspx page where the ColorChanged event is handled:

<%@ Page language="c#" %>
<%@ Register TagPrefix="cc1" Namespace="UNLV.IAP.WebControls" 

             Assembly="UNLV.IAP.WebControls.HtmlColorDropDown" %>
<script runat="server">
   private void HtmlColorDropDown1_ColorChanged(object sender, 
                                           System.EventArgs e)
     Label1.Text = HtmlColorDropDown1.SelectedColorName;
    <form runat="server">
      <cc1:HtmlColorDropDown id="HtmlColorDropDown1" runat="server" 

                  DisplaySelectColorItemText="--Select a Color--"



      <P>The selected color is: <asp:Label id="Label1" runat="server"/></P>

See the downloadable control documentation for a complete description of all HtmlColorDropDown properties and events.

The Issue: Persisting the Collection of UserDefinedColors

This control was designed with both visual designer (e.g., Visual Studio) and text editor (e.g., Notepad) environments in mind. For designer environments, we inherit much functionality without any extra code. Because we're using regular System.Drawing.Color objects for the SelectedColor property for example, the standard ColorBuilder becomes available within the Visual Studio web form designer.

Likewise, as we have standard Color objects within the UserDefinedColors collection, the Visual Studio collection builder is available at no charge:

A problem occurs however when it comes time to serialize this color collection into the server tag HTML. Typically, we would set the PersistenceMode and DesignerSerializationVisibility attributes on the collection property to have the collection items persisted as nested tags, like so:

public ColorCollection UserDefinedColors
    get {...}
    set {...}

With these attributes set, we can get the UserDefinedColors collection persisted. The markup, however, appears as verbose <System.Drawing.Color> tags, like the following:

<cc1:htmlcolordropdown id="HtmlColorDropDown1" runat="server"  

    <System.Drawing.Color IsEmpty="False" A="255" B="0" IsNamedColor="True" 

        IsKnownColor="True" Name="Red" G="0" R="255" IsSystemColor="False">
    <System.Drawing.Color IsEmpty="False" A="255" B="0" IsNamedColor="True" 

        IsKnownColor="True" Name="Green" G="128" R="0" IsSystemColor="False">
    <System.Drawing.Color IsEmpty="False" A="255" B="255" IsNamedColor="True" 

        IsKnownColor="True" Name="Blue" G="0" R="0" IsSystemColor="False">

The problem isn't only in the fact that there is much more information about the colors persisted than we need or want. As the attributes represent read-only properties of the Color object, an exception will be thrown upon parsing. It would be preferable to persist these inner items differently, with minimal information necessary, like the following:

<cc1:htmlcolordropdown id="HtmlColorDropDown1" runat="server"  

    <Color value="Red"/>
    <Color value="Green"/>
    <Color value="Blue"/>

This also makes the control easier to work with for those using plain text editors. A custom ControlDesigner can help us here in persisting the inner markup in this simplified manner, while a custom ControlBuilder will help deserialize the <Color value="xxx"/> tags upon parsing.

Custom Persistence through a ControlDesigner

In order to persist the UserDefinedColors collection, we'll define a custom subclass of System.Web.UI.Design.ControlDesigner. A ControlDesigner's purpose is to provide design-time support for a web control, and it can do so in a number of ways. For example, a ControlDesigner can be used to customize the HTML that is used to represent a control in a visual designer like Visual Studio. A ControlDesigner may also be used to add support for the visual editing of control templates.

For the HtmlColorDropDown control, we need the ability to customize the inner HTML that is serialized when a visual designer persists the object's properties to a web page. For this, we can subclass ControlDesigner and override the GetPersistInnerHtml method. The complete code for the subclassed HtmlColorDropDownDesigner is as follows:

public class HtmlColorDropDownDesigner : ControlDesigner
    public override string GetPersistInnerHtml()
        StringWriter sw = new StringWriter();
        HtmlTextWriter html = new HtmlTextWriter(sw);

        HtmlColorDropDown dd 
            = this.Component as HtmlColorDropDown;
        if (dd != null)
            // for each color in the collection, output its
            // html known name (if it is a known color)
            // or its html hex string representation
            // in the format:
            //   <Color value='xxx' />
            foreach(Color c in dd.UserDefinedColors)
                string s = 
                    (c.IsKnownColor ? c.Name 
                      : ColorUtility.ColorToHexString(c) );

                html.WriteAttribute("value", s);


        return sw.ToString();


In the overridden GetPersistInnerHtml method, we iterate through each System.Drawing.Color item in the UserDefinedColors property. For each color, we output a child tag in the form:

<Color value="xxx">

where xxx is either the name of the color (for known color items such as "Red") or its HTML hex string (e.g., "#FF0000"). Through this custom persistence, we can represent the full UserDefinedColors collection without the problems and verbosity of serializing full Color objects.

It is worthwhile to note that other methods are available for customizing how a control's properties are to be persisted. A TypeConverter, for example, may be defined for custom types, which can then play a role in serialization. For that matter, a custom CodeDomSerializer object can persist object properties as programming code rather than HTML. In the case of the HtmlColorDropDown control, I chose a custom ControlDesigner overriding GetPersistInnerHtml as it offered a simple and direct solution for persisting the contents of the ColorCollection.

The custom designer is associated with the main HtmlColorDropDown control through the Designer attribute. Other attributes are also important in this context. The PersistChildren(false) attribute is applied to the control to ensure that properties are not otherwise persisted as nested server control tags. The PersistenceMode and DesignerSerializationVisibility attributes are still applied to the UserDefinedColors property to ensure that our designer's GetPersistInnerHtml method in fact has a reason to be called.

    //...(other attributes)...//
public class HtmlColorDropDown : Control, IPostBackDataHandler 
                     , IPostBackEventHandler, IAttributeAccessor
        //...(other attributes)...//
    public ColorCollection UserDefinedColors
        get {...}
        set {...}

Custom Parsing through a ControlBuilder

The custom HtmlColorDropDownDesigner takes care of persisting the UserDefinedColors collection as inner HTML content of the server tag. When the page is parsed, three separate classes work together to deserialize this inner content back into the UserDefinedColors collection: a custom ControlBuilder, a helper class representing a <Color value='xxx'/> tag, and the main HtmlColorDropDown control itself.

The first of the three is a subclass of System.Web.UI.ControlBuilder. A ControlBuilder object assists the page parser when building a server control from markup text. The HtmlColorDropDownBuilder is defined as follows with only one overridden method:

public class HtmlColorDropDownBuilder : ControlBuilder
    public override Type GetChildControlType(string tagName, 
                                          IDictionary attribs)
        if (string.Compare(tagName,"color", true) == 0)
            return typeof(ColorItemHelper);

        return base.GetChildControlType (tagName, attribs);

The custom builder's GetChildControlType method returns the type ColorItemHelper for each <Color value='xxx'> child tag nested within the server control markup. The ColorItemHelper class is defined very simply:

public class ColorItemHelper
    private string _value;
    public string Value
        get {return _value;}
        set {_value = value;}

The custom builder is assigned to the HtmlColorDropDown control through the ControlBuilder attribute. The main HtmlColorDropDown control then uses the ColorItemHelper object passed to it from the parser to add the color to its UserDefinedColors collection. This is done by overriding the AddParsedSubObject method of the Control class:

    //...(other attributes)...//
    , ParseChildren(false)
    , ControlBuilder(typeof(HtmlColorDropDownBuilder))
public class HtmlColorDropDown : Control, IPostBackDataHandler 
                     , IPostBackEventHandler, IAttributeAccessor

    protected override void AddParsedSubObject(object obj)
        if (obj is ColorItemHelper)
            ColorItemHelper h = obj as ColorItemHelper;
            base.AddParsedSubObject (obj);


Note that the ParseChildren(false) attribute is applied to the main HtmlColorDropDown class. This ensures that the nested inner HTML is not parsed as properties of the control, allowing our custom parsing to function.


The HtmlColorDropDown web control renders a standard HTML <select> tag with <option> items representing color choices. The colors themselves may be rendered as the background or foreground color of each item. Three built-in palettes are offered; a fourth, UserDefined, allows a control user to specify which colors to provide as choices in the list. To support the persistence of user defined colors within a visual designer, I used a custom ControlDesigner, overriding the GetPersistInnerHtml method to render colors as simple <Color value='xxx'/> child tags. I also used a custom ControlBuilder to assist in parsing the nested tags for the deserialization of the UserDefinedColors collection. While techniques for custom property persistence and parsing may be tricky, such techniques offer important benefits for control authors and are worth consideration.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Mike Ellison
United States United States
I work for the University of Nevada, Las Vegas in the Office of Institutional Analysis and Planning. Among other things, our office is charged with the mission of deriving useful information in support of administrative decision-making from institutional data. Within the context of that mission, my office mates and I apply technology in the form of custom data processing applications, data extraction and analysis tools, reporting tools, relational databases, OLAP solutions, data warehousing, and data mining.

Visit my blog at

You may also be interested in...


Comments and Discussions

QuestionAwesome Pin
Rob_Jurado16-Jan-14 12:29
memberRob_Jurado16-Jan-14 12:29 
Questioncolor palette Pin
jyotianand14-Apr-13 8:19
memberjyotianand14-Apr-13 8:19 
GeneralMy vote of 5 Pin
manoj kumar choubey3-Feb-12 19:34
membermanoj kumar choubey3-Feb-12 19:34 
GeneralMy vote of 5 Pin
Sunasara Imdadhusen2-Jul-11 0:22
memberSunasara Imdadhusen2-Jul-11 0:22 
QuestionHow to create nested TAG component Pin
Sunasara Imdadhusen2-Jul-11 0:22
memberSunasara Imdadhusen2-Jul-11 0:22 
QuestionHow do you set a custom name for a user defined color? Pin
Member 454777024-Sep-09 2:26
memberMember 454777024-Sep-09 2:26 
QuestionFlat DropDownList Pin
priyaar10-Apr-09 22:17
memberpriyaar10-Apr-09 22:17 
Questioncan not work in listview of VS2008 Pin
jxnchk26-Feb-08 21:01
memberjxnchk26-Feb-08 21:01 
AnswerRe: can not work in listview of VS2008 Pin
Mike Ellison28-Nov-08 4:45
memberMike Ellison28-Nov-08 4:45 
GeneralAttaching to an validation control... Pin
Member 45342466-Feb-08 6:34
memberMember 45342466-Feb-08 6:34 
GeneralRe: Attaching to an validation control... Pin
Mike Ellison28-Nov-08 4:43
memberMike Ellison28-Nov-08 4:43 
QuestionHow Set Color For HtmlColorDropDown in Server code? Pin
zohreh_r10-Dec-07 19:48
memberzohreh_r10-Dec-07 19:48 
AnswerRe: How Set Color For HtmlColorDropDown in Server code? Pin
Mike Ellison28-Nov-08 4:42
memberMike Ellison28-Nov-08 4:42 
QuestionApplying a collection property Pin
dekelc27-Sep-07 16:54
memberdekelc27-Sep-07 16:54 
AnswerRe: Applying a collection property Pin
Mike Ellison23-Oct-07 8:07
memberMike Ellison23-Oct-07 8:07 
QuestionBackground color changes when mouse over Pin
palulu29-Aug-07 8:13
memberpalulu29-Aug-07 8:13 
AnswerRe: Background color changes when mouse over Pin
Mike Ellison23-Oct-07 8:09
memberMike Ellison23-Oct-07 8:09 
General4-pixel margin around checkboxes Pin
stdtime25-Apr-07 15:58
memberstdtime25-Apr-07 15:58 
GeneralRe: 4-pixel margin around checkboxes Pin
Mike Ellison26-Apr-07 5:51
memberMike Ellison26-Apr-07 5:51 
QuestionNeed idea for parsing Pin
Ramesh.A19-Jul-06 4:35
memberRamesh.A19-Jul-06 4:35 
AnswerRe: Need idea for parsing Pin
Mike Ellison19-Jul-06 6:02
memberMike Ellison19-Jul-06 6:02 
GeneralRe: Need idea for parsing Pin
Ramesh.A19-Jul-06 20:15
memberRamesh.A19-Jul-06 20:15 
GeneralRe: Need idea for parsing Pin
Mike Ellison20-Jul-06 6:02
memberMike Ellison20-Jul-06 6:02 
GeneralRe: Need idea for parsing Pin
Ramesh.A21-Jul-06 22:24
memberRamesh.A21-Jul-06 22:24 
GeneralRe: Need idea for parsing Pin
Mike Ellison22-Jul-06 7:30
memberMike Ellison22-Jul-06 7:30 
Generalcollection class in Pin
surshbabuk12-Jul-06 20:01
membersurshbabuk12-Jul-06 20:01 
GeneralRe: collection class in Pin
Mike Ellison13-Jul-06 5:37
memberMike Ellison13-Jul-06 5:37 
GeneralUse in a commercial application Pin
beanto30-May-06 12:31
memberbeanto30-May-06 12:31 
GeneralRe: Use in a commercial application Pin
Mike Ellison2-Jun-06 5:36
memberMike Ellison2-Jun-06 5:36 
GeneralRun-Time Binding and postback Pin
Sean Stapleton13-Mar-06 5:32
memberSean Stapleton13-Mar-06 5:32 
GeneralRe: Run-Time Binding and postback Pin
Mike Ellison14-Mar-06 11:22
memberMike Ellison14-Mar-06 11:22 
GeneralRe: Run-Time Binding and postback [modified] Pin
Jozzle6-Sep-06 12:46
memberJozzle6-Sep-06 12:46 
GeneralRe: Run-Time Binding and postback Pin
Jozzle6-Sep-06 13:52
memberJozzle6-Sep-06 13:52 
QuestionHow to Implement String-Editor ... Pin
ZarrinPour23-Feb-06 21:18
memberZarrinPour23-Feb-06 21:18 
AnswerRe: How to Implement String-Editor ... Pin
Mike Ellison24-Feb-06 5:58
memberMike Ellison24-Feb-06 5:58 
GeneralQuestion related to colection property Pin
Casp19-Oct-05 10:30
memberCasp19-Oct-05 10:30 
GeneralRe: Question related to colection property Pin
Mike Ellison20-Oct-05 6:34
memberMike Ellison20-Oct-05 6:34 
Generalinner tag like &lt;cc1:Color=&quot;Black&quot;/&gt; Pin
Anonymous13-Oct-05 3:15
sussAnonymous13-Oct-05 3:15 
GeneralRe: inner tag like &lt;cc1:Color=&quot;Black&quot;/&gt; Pin
Mike Ellison13-Oct-05 5:47
memberMike Ellison13-Oct-05 5:47 
GeneralRe: inner tag like &lt;cc1:Color=&quot;Black&quot;/&gt; Pin
Casp14-Oct-05 6:32
memberCasp14-Oct-05 6:32 
GeneralRe: inner tag like &lt;cc1:Color=&quot;Black&quot;/&gt; Pin
Casp14-Oct-05 6:36
memberCasp14-Oct-05 6:36 
GeneralRe: inner tag like &lt;cc1:Color=&quot;Black&quot;/&gt; Pin
Mike Ellison16-Oct-05 8:19
memberMike Ellison16-Oct-05 8:19 
GeneralPure HTML Pin
salle787-Oct-05 3:21
membersalle787-Oct-05 3:21 
GeneralSetting Selected Color not works in webcontrol Pin
bmo_13-Jun-05 22:03
memberbmo_13-Jun-05 22:03 
GeneralRe: Setting Selected Color not works in webcontrol Pin
Mike Ellison12-Jul-05 10:46
memberMike Ellison12-Jul-05 10:46 
GeneralControl Ussage Pin
jouin@webfoxmail.com29-Apr-05 15:35
sussjouin@webfoxmail.com29-Apr-05 15:35 
GeneralRe: Control Ussage Pin
Mike Ellison2-May-05 6:04
memberMike Ellison2-May-05 6:04 
GeneralThe only missing thing Pin
D. Emilio Grimaldo Tuñon3-Apr-05 3:48
memberD. Emilio Grimaldo Tuñon3-Apr-05 3:48 
GeneralRe: The only missing thing Pin
Mike Ellison4-Apr-05 6:45
memberMike Ellison4-Apr-05 6:45 
GeneralControlBuilder in wrong namespace Pin
MR_SAM_PIPER26-Jan-05 11:41
memberMR_SAM_PIPER26-Jan-05 11:41 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170424.1 | Last Updated 27 Jan 2005
Article Copyright 2004 by Mike Ellison
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid