DropDownList with OptionGroup






4.79/5 (21 votes)
An ASP.NET DropDownList custom control with the HTML OptionGroup feature.
Introduction
ASP.NET 2.0 lacks the OptionGroup functionality (<optgroup>
) in the DropDownList
control. This means that it is not possible to obtain a select control as shown below:
Using the code
To work around this limitation, I built a user render control, available for .NET Framework 2.0 or later, with this functionality. This control supports the following features (as do the System.Web.UI.DropDownList
control built in the .NET framework):
EnableViewState
propertyAutoPostBack
propertyAppendDataBoundItems
propertySelectedValue
propertySelected
property for child items- Raises the
ValueChanged
event - Supports
DataBind
You can use the control at design-time as shown below:
<ddlb:optiongroupselect id="OptionGroupSelect1" runat="server" enableviewstate="true">
<ddlb:OptionGroupItem ID="OptionGroupItem1"
runat="server" Value="1" Text="ONE" OptionGroup="Odd" />
<ddlb:OptionGroupItem ID="OptionGroupItem2"
runat="server" Value="2" Text="TWO" OptionGroup="Even" />
<ddlb:OptionGroupItem ID="OptionGroupItem3"
runat="server" Value="3" Text="TREE" OptionGroup="Odd" />
<ddlb:OptionGroupItem ID="OptionGroupItem4"
runat="server" Value="4" Text="FOUR" OptionGroup="Even" />
</ddlb:optiongroupselect>
It is not necessary that items that belong to the same OptionGroup be placed close.
Or, if you prefer to use the control in code:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.OptionGroupSelect1.Items.Add(new OptionGroupItem("A",
"Letter A", "Letters"));
this.OptionGroupSelect1.Items.Add(new OptionGroupItem("B",
"Letter B", "Letters"));
this.OptionGroupSelect1.Items.Add(new OptionGroupItem("C",
"Letter C", "Letters"));
}
}
Points of interest
The solution attached to this article is composed of two projects. The first one is a class library, where there are the sources for the control and its related classes, and the second one is a web application, where there are some pages to test the control behavior.
In the project library, we can find the following classes:
OptionGroupSelect
is the control. It inherits from theDataBoundControl
that, at the end, extends theWebControl
class. I extend theDataBoundControl
class because it is used as the base class for all ASP.NET 2.0 data-bound controls that display their data in list form. This base class gave me the functionality to perform the data binding operation for the render control.OptionGroupItem
represents the single “list item” with the relative properties:Text
,Value
,OptionGroup
, andSelected
. It inherits from theWebControl
class and simply overrides theRender
method.OptionGroupSelectControlDesigner
is used to perform the design-time control rendering.OptionGroupItemBuilder
is used to notify the parent control, theOptionGroupSelect
, that an HTML element has been analyzed and added to the parent’s ControlCollection property. Essentially, it allows me to create the child items at design-time.
The main control (OptionGroupSelect
) overrides the LoadViewState
method to retrieve the view state value, used to maintain the control state. Consequently, the SaveViewState
is overridden too.
Because the control implements the IPostBackDataHandler
interface, the LoadPostData
method is overridden to detect if the selected value is changed from any user selection. In that case, it returns true, so the ValueChanged
event is triggered.
Within the Render
method, I draw the select
HTML control, adding the optgroup
element, and for each child list item, call the relative RenderControl
method.
If the child items define the OptionGroup
property, I group them by this value, so items with the same OptionGroup
are arranged close. Items without the OptionGroup
value are treated normally.
As I said, the mail control extends the DataBoundControl
class. This means that some methods have to be overridden to obtain the data-bound behavior. These methods are:
PerformSelect
: This method is invoked due to theDataBind
call. It extracts the data source and exposes it as anIEnumerable
object. The interesting thing is that the data source object doesn’t have to be aDataSet
. It also acceptsDataTable
,DataView
, orList<OptionGroupItem>
. Moreover, the methodthis.GetData()
used inside the code extracts from theDataSet
aDataSourceView
object that points to the specifiedDataTable
indicated by theDataMember
property.PerformDataBinding
: This method executes the real work. For each item, anOptionGroupItem
instance is created and added to theOptionGroupSelect
childControls
collection.
More details about custom data-binding can be found at MSDN.