A collection of learnings and opinions.

Thursday, August 2, 2007

DropDownList with a blank item on top

The DropDownList (DDL) is a nice little databindable control in ASP.Net. The easiest way to use it is to databind it to some value from your database and let the user select.

The problem with straight on databinding is that the first item in the DDL will be the first item in the databound collection (naturally), thus making choosing that item "a little too easy" and "a little too hard". When the user wants to select the top item you might be in for problems, as that selection won't fire off a SelectedIndexChanged -event, which is what you'd normally listen for.

There are ways around this - I've seen several suggestions. None of these are even starters in my opinion:
  • Don't handle changes in the DDL, read from it on some other event (typically a button)
    • This makes it very hard to create responsive UIs, as your user will always have to keep clicking buttons
  • Set whatever you want to happen on changes in the DDL as if the first choice was already chosen (pre-choose for the user)
    • Badness - especially in a stateless media like the web - your user may never correct your initial (possibly wrong) assumption
  • Add an empty record in the databound object (typically your database)
    • Perhaps the worst idea I've seen. The database should not contain filler like this. It's a bit better if you're working with some transient object - but still it's a hack. We don't like hacks.
The way to fix this problem is really not very hard. What you want is an empty item on the top of the list that the user will not expect to work, with a known value you can check for in your SelectedIndexChanged handler.

To do this add a ListItem to the DDL in the page/control's definition with your sentinel value and an empty string as the Text property. Normally this item would disappear on databinding, but wait: set the AppendDataBoundItems property on the DDL to True, and your empty initial value will survive!

Two things to beware: Make sure you check for your sentinel value in the handler, and remember to clear all but the initial item of the DDL's ItemListCollection if you're databinding that control again later (unless you want to keep appending).

Here's your illustrative code:
A standard DDL:

<asp:DropDownList id="ddBasic" runat="server" autopostback="True">
<!-- Selecting the top item will not fire an event (it will be pre-selected) -->

A DDL with the empty top-item:

<asp:DropDownList id="ddWithEmptyTop" runat="server" autopostback="True" appenddatabounditems="True">
<asp:ListItem value="-1" text=""> </asp:ListItem>

Technorati Tags: , , ,