One of the common use web control is DropDownList. It provides an easy way of server side data binding to the list, it can be bound to ArrayList or DataTable data, for example. The problem arises when I need to use this control to bind the data from the client side in javascript array.

Using Visual Studio 2003, I created a simple ASP.NET Web application project that has a TestPage.aspx webpage. The page will have a DropDownList, a Button, and a Label control. The page will be like below (the head and body part):

  <head>
    <title>TestPage</title>
    <meta name="vs_showGrid" content="False">
    <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
    <meta name="CODE_LANGUAGE" Content="C#">
    <meta name="vs_defaultClientScript" content="JavaScript">
    <meta name="vs_targetSchema"
        content="http://schemas.microsoft.com/intellisense/ie5">
    <script language="javascript" src="dd_render.js"></script>
    <script language="javascript" src="testdata.js"></script>
  </head>
  <body>
    <form id="frmTest" method="post" runat="server">
      <asp:DropDownList id="ddlTest" runat="server"></asp:DropDownList>
      <asp:Button id="btnSubmit" runat="server" Text="Submit"></asp:Button><br>
      <asp:Label id="lblTest" runat="server"></asp:Label>
      <script language="javascript">
      __genDDData(''ddlTest'', ''SomeData'', true, ''A'');
      </script>
    </form>
  </body>

The dd_render.js file contains the __genDDData javascript function which used to render the data, as follow:

function __genDDData(comboBoxId, arrayName, showBlankItem, selectedValue)
{
  var codeArray, descArray;
  var opt;
  var cb = document.getElementById(comboBoxId);
  var separator = ''~''; // this is hardcoded for control
  var emptyString = '''';
  try
  {
    eval("codeArray=" + arrayName + "_cd");
    eval("descArray=" + arrayName + "_desc");
  }
  catch (e)
  {
    // skip to generate js droplist
    return;
  }

  if (showBlankItem)
  {
    opt = document.createElement("OPTION");
    opt.text = emptyString;
    opt.value = emptyString + separator;
    cb.options.add(opt);
  }

  if (codeArray != null && codeArray.length != null)
  {
    for (index = 0; index < codeArray.length; index++)
    {
      if (selectedValue != '' && selectedValue == codeArray[index])
      {
        opt = document.createElement("OPTION");
        opt.selected = true;
      }
      else
      {
        opt = document.createElement("OPTION");
      }
      opt.value = codeArray[index] + separator + descArray[index];
      opt.text = descArray[index];
      cb.options.add(opt);
    }
  }
}

The function will create two variables to hold the array data of arrayName + “_cd” and arrayName + “_desc” as dropdownlist value and text. The testdata.js file contains the javascript array variable as source data to bind as sample, as follow:

var SomeData_cd = new Array("A","B","C","D","E","F","G","H","I");
var SomeData_desc = new Array("Data A","Data B","Data C","Data D",
   "Data E","Data F","Data G","Data H","Data I");
var SomeData2_cd = new Array("1","2","3","4","5","6","7","8","9");
var SomeData2_desc = new Array("Data 1","Data 2","Data 3","Data 4",
   "Data 5","Data 6","Data 7","Data 8","Data 9");

The button Click event is wired to show the postback data of selected value of the dropdownlist. The code is as below:

private void btnSubmit_Click(object sender, System.EventArgs e)
{
    lblTest.Text = "Dropdownlist data: " + ddlTest.SelectedValue;
}

Compile the code, and try to load the TestPage.aspx, and you will have the ddlTest dropdownlist data bound. Try to click on the Submit button, you will see that the selected value is empty.
It seems like the built-in DropDownList control can capture the selected value when its data was bound from server side (through ViewState). To overcome this, I created a simple ASP.NET dropdownlist control that will maintain the selected value after postback, which I name it JSDropDownList. The source is available to download in this article, together with the sample application to test.

To use this control, you need to add the reference to the assembly (JSDropDownList.dll) file into the project, and in the TestPage.aspx page itself, you need to register the control at the page declaration, as follow (the TagPrefix is what you want to put). For example, I have added two more JSDropDownList and Label controls inside the page for testing purpose.

<%@ Register TagPrefix="ccl" Namespace="funcode.WebControl" Assembly="JSDropDownList" %>
...
    <asp:DropDownList id="ddlTest" runat="server"></asp:DropDownList>
    <ccl:JSDropDownList id="ddlJS" runat="server" TableName="SomeData" />
    <ccl:JSDropDownList id="ddlJS2" runat="server" TableName="SomeData2" />
    <asp:Button id="btnSubmit" runat="server" Text="Submit" />
    <asp:Label id="lblTest" runat="server"></asp:Label><br/>
    <asp:Label id="lblTest2" runat="server"></asp:Label><br/>
    <asp:Label id="lblTest3" runat="server"></asp:Label><br/>
...

The button Click event handler has been modified to show the selected value of the two new JSDropDownList control selected values.

private void btnSubmit_Click(object sender, System.EventArgs e)
{
    lblTest.Text = "Dropdownlist data: " + ddlTest.SelectedValue;
    lblTest2.Text = "JS Dropdownlist 1 data: " + ddlJS.SelectedValue +
        ''='' + ddlJS.SelectedText;
    lblTest3.Text = "JS Dropdownlist 2 data: " + ddlJS2.SelectedValue +
        ''='' + ddlJS.SelectedText;
}

Load the page to try, the postback after clicking button will set the selected value of ddlJS and ddlJS2 to the labels.
ASP.NET image
The first time when the control is loaded.

ASP.NET image 2

Try to select some values, and click on the Submit button

ASP.NET image 3

The labels display the selected value/text of control, except for the built-in DropDownList.
Why do we such a control? The reason that I can think of is save bandwidth, in the condition like:

  • the data seldom or never change, downloading the js file to client machine will be when there is a change. Once it is in the client machine, it can be used by multiple controls.
  • the data is long, for example country code/name lookup field. The one time download will be better than binding the data at server side and send the whole page to the browser, as the page size could be big.

Download the source for this article: Custom DropDownList Control Files

Popularity: 11% [?]