Creating Linked Drop-Down Lists with the CascadingDropDown Control

Creating dependant drop-down lists is a very common task, for example, when making a registration form, you usually have to add a country and a state fields, the contents of the state drop-down depends on the selected item in the country drop down field. Actually, it's not so difficult to implement that with the standard controls of ASP.NET. However if you don't want the page to be reloaded every time a user selects a value in the drop-down list, you should make use of AJAX. While you can use UpdatePanel for this task, it will be difficult if you have 3 or even linked drop-downs. Hopefully, you don't have to add a lot of UpdatePanels, instead you can pick up the CascadingDropDown Control from ASP.NET AJAX Control Toolkit. You can see the demo here. CascadingDropDown is an extender for the standard DropDown control that retrieves the data from a web service. In the example, we'll create 4 linked drop-downs - for the continent, for the country, for the territory and for the city.

Continent: <asp:DropDownList ID="ddlContinent" runat="server" />
<cc1:CascadingDropDown
  ID="cddContinent"
  runat="server"
  TargetControlID="ddlContinent"
  Category="continent"
  ServicePath="Helper.asmx"
  ServiceMethod="GetContinents"
/>
<br />
Country: <asp:DropDownList ID="ddlCountry" runat="server" />
<cc1:CascadingDropDown
  ID="ccdCountry"
  runat="server"
  TargetControlID="ddlCountry"
  ParentControlID="ddlContinent"
  Category="country"
  ServicePath="Helper.asmx"
  ServiceMethod="GetCountries"
/>
<br />
Territory: <asp:DropDownList ID="ddlTerritory" runat="server" />
<cc1:CascadingDropDown
  ID="ccdTerritory"
  runat="server"
  TargetControlID="ddlTerritory"
  ParentControlID="ddlCountry"
  Category="territory"
  ServicePath="Helper.asmx"
  ServiceMethod="GetTerritories"
/>
<br />
City: <asp:DropDownList ID="ddlCity" runat="server" />
<cc1:CascadingDropDown
  ID="ccdCity"
  runat="server"
  TargetControlID="ddlCity"
  ParentControlID="ddlTerritory"
  Category="city"
  ServicePath="Helper.asmx"
  ServiceMethod="GetCities"
/>

I must explain some attributes we have here:

ParentControlID - the ID of the parent drop-down control Category - the key of the collection we parse in a web service. I'll explain it below. ServicePath - the path to a web service the control gets the data from ServiceMethod - the name of the method the control invokes to retrieve the data Let's proceed to the web service now. First, we should mark it with ScriptService attribute:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class Helper : System.Web.Services.WebService

Then, the methods we are going to invoke must have the following signature:

[WebMethod]
public CascadingDropDownNameValue[] MethodName(string knownCategoryValues, string category)

The parameters names should match as well:

  • knownCategoryValues - contains the values of the all chosen cascading-drop downs. It can be transformed to a collection by CascadingDropDown.ParseKnownCategoryValuesString() method, which return the StringDictionary collection, the keys of the collection math the Category attributes of CascadingDropDowns.
  • category - contains the value of the Category atttribute of the CascadingDropDown that invokes the current method.

Some sample methods:

[WebMethod]
public CascadingDropDownNameValue[] GetContinents(string knownCategoryValues, string category)
{
CascadingDropDownNameValue[] continents = new CascadingDropDownNameValue[2];
continents[0] = new CascadingDropDownNameValue("North America", "North America");
continents[1] = new CascadingDropDownNameValue("Europe", "Europe");
return continents;
}

[WebMethod]
public CascadingDropDownNameValue[] GetCountries(string knownCategoryValues, string category)
{
StringDictionary ddlData = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
string continent = ddlData["continent"];

    List<CascadingDropDownNameValue> countries = new List<CascadingDropDownNameValue>();

    if (continent == "North America")
    {
        countries.Add(new CascadingDropDownNameValue("United States", "United States"));
        countries.Add(new CascadingDropDownNameValue("Canada", "Canada"));
    }
    else if (continent == "Europe")
    {
        countries.Add(new CascadingDropDownNameValue("United Kingdom", "United Kingdom"));
        countries.Add(new CascadingDropDownNameValue("France", "France"));
    }
    else
    {
        countries.Add(new CascadingDropDownNameValue("N/A", "N/A"));
    }

    return countries.ToArray();
}

Conclusion

CascadingDropDown is a very powerful AJAX enabled control that should be used when you have two or more linked drop-down lists. You can read more here and there.

Mike Borozdin (Twitter)
13 August 2008

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way. My personal thoughts tend to change, hence the articles in this blog might not provide an accurate reflection of my present standpoint.

© Mike Borozdin