Click here to Skip to main content
Click here to Skip to main content

Multi-column dropdown combobox - an ASP.NET 2.0 server control

By , 9 Feb 2006
 

Introduction

This code drop is part of a smash and grab series. If you're in a rush, you can just grab this code and insert it into your application, no understanding is required. When you have some time (ya, right), you may want to review the source code.

Background

I was presented with a project to convert an Access single-user application into a web-based multi-user SQL Server application. The Access application has a number of multicolumn dropdown lists and I couldn't find what I needed anywhere on the internet. So I wrote my own.

For this article, I have used the Products, Suppliers and Categories table in the NorthWind database.

Using the code

  • Download the project, unzip it to somewhere on your hard disk.
  • Create a new ASP.NET project.
  • Right click on the project and select Add existing item.
  • Navigate to the folder that you unzipped to, and select the .JS and .GIF files.
  • Create a bin folder for the project.
  • Right click on bin and choose Add existing item.
  • Select Tools > Choose toolbox items.
  • Navigate to the unzip folder and select the DLL.
  • This new server control now appears in the toolbox under General.
  • Drag an instance of it onto Default.aspx.
  • Drag an instance of SqlDataSource onto Default.aspx.
  • Configure the datasource to use the custom SQL statement:
    SELECT Products.ProductID, Products.ProductName, 
        left(Products.ProductName+SPACE(40),40)+Suppliers.CompanyName as Name, 
        Categories.CategoryName 
    FROM Products 
    INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID 
    INNER JOIN Suppliers ON Products.SupplierID = Suppliers.SupplierID 
    order by Categories.CategoryName, Products.ProductName

Set these properties on the DropDownComboControl:

  • DropDownCssStyle: font-family: monospace; background-color: yellow
  • DropDownCssClass:
  • DropDownMonospace: true
  • DropDownSize: 10
  • TextBoxCssStyle: background-color: blue
  • TextBoxCssClass:
  • TextBoxColumns: 20
  • TextBoxMaxLength: 30
  • PickOnly: false
  • onchange: SetTextBox(this, this.options[this.selectedIndex].extra);
  • DataExtraField: ProductName
  • DataOptGroup: CategoryName
  • DataSourceID: SqlDataSource1
  • DataTextField: Name
  • DataValueField: ProductID
  • ImageFolder: .
  • ImageWidth: 26
  • ScriptFolder: .

Other than DataSourceID, DataTextField and DataValueField, all the other properties listed are new. The control consists of a textbox (<input> element) and a dropdownlist (<select> element).

Properties of interest:

  • Border: (1px solid InactiveBorder) sets the border of the control.
  • DropDownCssClass: sets the class attribute of the <select> element.
  • DropDownCssStyle: sets the style attribute of the <select> element.
  • DropDownSize: sets the size attribute of the <select> element.
  • TextBoxCssClass: sets the class attribute of the <input> element.
  • TextBoxCssStyle: sets the style attribute of the <input> element.
  • TextBoxColumns: sets the size attribute of the <input> element.
  • TextBoxMaxLength: sets the maxlength attribute of the <input> element.
  • PickOnly (true/false): when set to true you can only pick from the list, you can't enter a custom value.
  • DataOptGroup: the combo box can implement the <optgroup> functionality (see the screenshot above). This property tells the combo box which datafield contains the optgroup value. A new <optgroup> is created each time the specified value changes, so in the above SELECT statement, you can see that the ORDER BY clause is set to CatagoryName first.
  • DataExtraField: the combo box can place extra information in the <option> tag. For example: <option value="3" extra="coffee">coffee by martha</option> You will see later how this is used.
  • ImageFolder: this is the folder in which the dropdown image resides (. for current folder).
  • ImageWidth: the width of the dropdown image. The image provided is 26px.
  • ScriptFolder: this is the folder in which the JavaScript code resides (. for current folder).

In the screen shot above, you can see that the dropdown is a lot wider than the textbox. This allows you to present more information to the user about the selection, but once selected, consumes much less real-estate.

In the screen shot, I wanted the dropdown to be multi-column with the second column data aligned correctly. To do this, I needed to choose a fixed-width font:

  • DropDownCssStyle: font-family: 'courier new', 'monospace'

    I had to make sure that multiple spaces weren't collapsed into a single space as is the HTML standard. I did this by setting DropDownCollapseSpaces: false. This property tells the control to replace spaces with  - thus preserving spacing. The control will by default fill the text box with the selected dropdown entry.

In the example, I didn't want the company name in the textbox, so I added an OnClick event handler:

ComboWithAdjustableDropDownWidth.SetTextBox(this, 
                       this.options[this.selectedIndex].extra);

This takes the extra information (remember DataExtraField) that we stored in the <option> and puts it in the text box. You can set the OnClick handler to whatever you want.

Points of interest

The control also works with databinding for use in GridView, etc.

<cc1:combowithadjustabledropdownwidth 
     id="ComboWithAdjustableDropDownWidth1" runat="server" 
     ...
     SelectedValue='<%# Bind("SupplierID") %>
</cc1:combowithadjustabledropdownwidth>

You'll have to hand edit this into the source code, because VS2005 doesn't do it for you. In the source zip file, I have included a small project that shows databinding to a FormView element. The project also lists some other fixed pitch fonts.

Conclusions

There you go, a cheap (well free) ASP.NET 2.0 ComboBox that suits my needs and hopefully yours.

SmashGrab / Redux series

I have recently started two series of articles here at CodeProject. Smash and Grab is intended as a series of short articles on one specific code technique. Redux is intended as a series of longer articles which attempt to reduce a complicated topic (like GridView) into its basic constituent parts and show that once you have all the information, it wasn't really that hard after all. To find the Smash and Grab articles, search for the keyword SmashGrab. To find the Redux articles, search for the keyword Redux.

I welcome any contributions to either series, but please follow the guidelines when submitting articles to either.

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

About the Author

Gary Dryden
Software Developer (Senior)
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1memberprayerlin rex18 Jan '10 - 21:27 
ghyhk
Questionfree textmemberakan4717 Jul '09 - 4:56 
Does it allow free text
QuestionSet data value?membermichael.richardson.200228 Aug '08 - 3:42 
Is it possible to assign a value to this control?
GeneralParser Errormembermichael.richardson.200226 Aug '08 - 10:51 
Parser Error Message: Could not load file or assembly 'ComboWithAdjustableDropDownWidth' or one of its dependencies. The system cannot find the file specified.
 
Any ideas?
GeneralRe: Parser Errormembermichael.richardson.200227 Aug '08 - 10:22 
I think my issue was having the dll file in the wrong bin.
QuestionMultiple Column Drop DownmemberMember 233735927 Mar '08 - 18:38 
Hi,
I try to implement this sample application project in my project using ASP.NET framework 3.5 but nothing happen. No user control appear in my tool box list. Please guide me where i have to modify my code to use this user control.
Any suggestion or help is highly appreciated.
 
Thanks
QuestionMulti-column dropdown combobox [modified]memberhl785 Mar '08 - 23:57 
it's giving me System.NullReferenceException after compile, when i put the control on stage and before i even bind anything to it.
!!!!!!!!!!
 
modified on Thursday, March 6, 2008 7:06 AM

AnswerRe: Multi-column dropdown comboboxmemberMuneeeb30 Jun '08 - 22:49 
I am having the same issue.
 
I guess it is down to the fact that I am not binding any data source to it. I wonder if we can use this dropdown without binding data to it i.e. only to add data through adding items manually.
 
Gary, can you comment ?
 
Thanx
 
crap learner !

QuestionImages in the combo box?membermmengel11 Jan '08 - 6:50 
Gary:
 
Lots of goodness in this control. Does it (or will it) allow for using images in the combo box? For example, displaying an image/icon, then the text? Also, is there a property that is referenceable from the server-side code that will allow the user to see the selected text in the text box, but use a different value in on the server, similar to the DropDownlist.SelectedValue?
 
Thanks,
Mike
GeneralRe: Images in the combo box?memberGary Dryden11 Jan '08 - 7:04 
The generated HTML is a standard <option> list, so no you can't have an image.
To get the text of the selected item all you need is to have a hidden field on the form and in your submit javascript code have something like:
document.all.idOptionText.value=
document.all.idSelect.options[document.all.idSelect.selectedIndex].text </option>
GeneralDropDown behaviour on Custom Browser [modified]memberJohn Gathogo11 Jun '07 - 23:28 
I want to draw your attention to the behaviour of this multi-column dropdown combobox when the page containing it is loaded on a custom browser created using the WebBrowser Control that comes with Microsoft Visual Studio 2005. It is impossible to scroll using the vertical scrollbar. When you click on the scrollbar with an intention to scroll, it just closes. I tried this from a custom browser I created and also on another by Thomas Maxwell on Planet Source Code:
 
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=10&txtCodeId=5484[^]
 
with the same result.
On IE, its scrolling ability is OK. Is it possible that Microsoft's WebBrowser control might have some deficiencies?
 

-- modified at 5:37 Tuesday 12th June, 2007
GeneralUnable to use with MasterpagesmemberRAJESH M11 May '07 - 19:31 
Your control works fine when I use in an normal aspx page. However, I am unable to use this control when I use Master pages, I get an error, "
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
 
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
 
Source Error:
 
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
PLEASE HELP
 

 

 
regards
Rajesh
GeneralRe: Unable to use with MasterpagesmemberHookemHorns4 Oct '07 - 11:24 
I am having the same problem. Does anyone know of a solution?
GeneralRe: Unable to use with MasterpagesmemberEdin_el_Bosnewi9 Feb '08 - 4:23 
I have the same problem, How did you solve it... it can't be that even after a year you haven't figured it out... Thanks
Generaladd header and two columnsmemberdsmportal9 Apr '07 - 9:39 
i just need two columns like
 
product id produc name
----------------------------
12312 abc
234234 dfgsd
34123 dafadf
 
how do i do in this control?
 
thanks
Generaladd headermemberdsmportal9 Apr '07 - 9:32 
how can i add header of the columns?
GeneralMoving mouse over different options in the listmemberMember #369148715 Mar '07 - 23:20 
I have used this control in my project and its working great. But I have a small problem, when I move mouse over different options in the list, their background color is not getting changed to blue(on Windows XP machine with default theme) as in built-in dropdownlist control. Can anyone help me in this regard ?
 
Thanks
Ramakrishna
QuestionIE7 Compatibility??memberdougBR8 Dec '06 - 8:40 
Hello everybody,
 
I was wondering if anyone had any problems with this component on IE7. The component doesn't appear on the page correctly but it seems to work. I would like to know if there is a hot fix for this problem.
 
Thanks in advance!
GeneralATLmemberjeswanma3 Dec '06 - 19:56 
Hi i want to know that after selcting item from combobox when we hit enter then items mathcing with combobox entry will be highlighted in list control.
Ex:-if we select Error in combobox and press enter then all error matching keywords are highlightes in ListBox control.
If anyone knows this then plz reply..
 
Madhu
GeneralIssue in passing a Where clause to select statementmembermohanol10 Nov '06 - 6:46 
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:ftl_ConnectionString %>"
SelectCommand="SELECT DISTINCT hotels.Name, hotels.City, hotels.hotel_uid, sch000.sch000_uid FROM sch000 INNER JOIN ftl003 ON sch000.grantee_uid = ftl003.grantee_uid INNER JOIN hotels ON ftl003.hotel_uid = hotels.hotel_uid" ProviderName="<%$ ConnectionStrings:ftl_ConnectionString.ProviderName %>" FilterExpression="sch000_uid ={0}">
<SelectParameters>
<asp:SessionParameter Name="requestUid" SessionField="requestUid" />
</SelectParameters>

<asp:SessionParameter Name="requestUid" SessionField="requestUid" />


 
Mohan

GeneralSearchable drop downmembersaurabh7626 Sep '06 - 0:32 
Hi, I have tried this control. It's really cool... However i want to ask one thing. Can i make this control searchable? Meaning you type some value in text box and then hit enter and dropdown will populate with only relevant entries instead of all entries.
Let me know if someone knows how to do this. or is there any other control available freely!!!
Saurabh
GeneralRe: Searchable drop downmemberArnold Wiersma26 Feb '08 - 4:42 
Have you figured out how to do this? Because I would also like to have searchable box.
 
If anyone can help me with this that would be great.
 
Thanks in advance
General2 helpful modsmemberjohwat15 Aug '06 - 12:01 
I made 2 changes to your excellent control that make it even more useful.
First, u assume that the the data source is s SQLDataSource, but the following changes allow it to be any IEnumerable, and if you specify the DataSourceID to point to a ObjectDataSource, SqlDataSource or any other built in DataSource descendant, the framework actually does all the work of finding the datasource, executing the select, etc... so this is all that is needed:
 
            private IEnumerable _target = null;
 
            protected override void PerformDataBinding(IEnumerable data )
            {
                  base.PerformDataBinding(data);
                  _target = data;
            }
 
You can then use the saved _target in the Render method:
 
          protected override void RenderContents(HtmlTextWriter output)
          {
                  string LastOptgroup = null;
                  bool UsingOptgroup = this.DataOptgroupField != "";
                  bool GotSelectedValue = false;
                  if (_target != null)
                  {
                        foreach (object item in _target)
                        {
                              if (UsingOptgroup)
                              {
                                    // or GetPropertyValue instead of Eval, could also add in a format specifier overload with matching property
                                    string ThisOptgroup = (string)DataBinder.Eval(item, this.DataOptgroupField);
                                    if (ThisOptgroup != LastOptgroup)
                                    {
                                          if (LastOptgroup != null)
                                                output.Write("</optgroup>\r\n");
                                          LastOptgroup = ThisOptgroup;
                                          output.Write("<optgroup label=\"" + System.Web.HttpUtility.HtmlEncode(ThisOptgroup) + "\">\r\n");
                                    }
                              }
                              output.Write("<option value=\"");
                              string itemValue = DataBinder.Eval(item, this.DataValueField).ToString();
                              output.Write(System.Web.HttpUtility.HtmlEncode(itemValue) + "\" ");
                              if (this.DataExtraField != "")
                              {
                                    string extraValue = (string)DataBinder.Eval(item, this.DataExtraField);
                                    output.Write("extra=\"" + System.Web.HttpUtility.HtmlEncode(extraValue) + "\" ");
                              }
                              if ((!GotSelectedValue) && (itemValue==this.SelectedValue))
                              {
                                    output.Write(" selected=\"selected\"");
                                    GotSelectedValue = true;
                              }
                              output.Write(">");
                              string textValue = (string)DataBinder.Eval(item, this.DataTextField);
                              string Text = System.Web.HttpUtility.HtmlEncode(textValue);
                              if (this._collapse == false)
                                    Text = Text.Replace(" ", "&nbsp;");
                              output.Write(Text);
                              output.Write("</option>\r\n");
                        }
                        if (UsingOptgroup)
                        {
                              if (LastOptgroup != null)
                                    output.Write("</optgroup>\r\n");
                        }
                        if (!GotSelectedValue)
                        {
                              string Encoded = System.Web.HttpUtility.HtmlEncode(this.SelectedValue);
                              output.Write("<option value=\"" + Encoded + "\">" + Encoded + "</option>\r\n");
                        }
                  }
               }
 
Second, in the code that uses the ImageFolder and ScriptFolder, if you add a call to ResolveURL the control supports tildebased URLS like ~/Lib/Contols/
 
string img = this.ResolveUrl(_imgfolder + "/ComboWithAdjustableDropDownWidth.gif" );
 
and
 
this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "ComboWithAdjustableDropDownWidth", this.ResolveUrl( _scriptfolder+"/ComboWithAdjustableDropDownWidth.js"));
 
Cheers
 
John
 


 
John Waters
www.falafel.com
john@falafel.com
GeneralUsing scroll bar causes list to closememberGonzonia17 May '06 - 8:01 
When I go to click on the scroll bar to scroll, the list closes.
commenting out the line
this.Attributes.Add("onblur", "ComboWithAdjustableDropDownWidth.SetLastClose(); this.style.display='none';");
 
fixes the problem, except now it doesn't close until something is selected.
 

 
And suggestions?

Generaldatabindmemberalnp13 Apr '06 - 13:19 
do u have to use SqlDataSource at design time.
can it be bound at runtime?
 
thx..

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 10 Feb 2006
Article Copyright 2006 by Gary Dryden
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid