Thursday, May 7, 2009

C# How To: Cascading dropdowns on a Formview for Country\Region selection

This is something most ASP.Net apps deal with regularly, but I couldn't find one solid solution on the interwebs. I needed a user to select a country and then have the "Region" dropdown be populated with the expected list of regions (states, provinces, etc)
I hope this helps. If not, at least I'll remember how it's done.

FYI, I've intentionally left out some details around data access since I am using ObjectDataSources and you can handle data access however u need. I also assume that you have a simple FormView control working that can update a record in your database.

Steps:
1: Make sure 'EnableViewState=true' is on your ASPX page or Masterpage.
2: Make sure you have a field like Country and Region in the DataTable you are editing and make sure you can update these values through an objectdatasource, if you want this example to work.

3: Create an objectdatasource (ie. odsCountries) that returns a list of Countries and bind to ddlCountry.

<asp:ObjectDataSource ID="odsCountries" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetCountries" TypeName="BLL">
</asp:ObjectDataSource>

4: Create an objectdatasource (ie. odsRegions) that returns a list of Regions with a Country parameter and bind to ddlCountry.

<asp:ObjectDataSource ID="odsRegions" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetRegions" TypeName="BLL">
<SelectParameters>
<asp:ControlParameter ControlID="editForm$ddlCountry" Name="Country"/>
</SelectParameters>
</asp:ObjectDataSource>


5: Add a Country dropdownlist to the Formview's edit template (ie. ddlCountry)

<asp:DropDownList ID="ddlCountry" runat="server" SelectedValue='<%# Bind("COUNTRY") %>' DataSourceID="odsCountries"
OnDataBound="ddlCountry_DataBound" DataTextField="Country" DataValueField="Country" AutoPostBack="True"></asp:DropDownList>


6: Add a Region dropdownlist to the Formview's edit template (ie. ddlRegion)

<asp:DropDownList ID="ddlRegion" DataSourceID="odsRegions" runat="server" AutoPostBack="True"
DataTextField="REGION" OnDataBound="ddlState_DataBound"/>


7: Create 2 DataBound EventHandlers for each DropDownlist

protected void ddlCountry_DataBound(object sender, EventArgs e)
{
DropDownList ddlCountry = (DropDownList)sender;
ListItem li = new ListItem("Choose a Country", "");
ddlCountry.Items.Insert(0, li);

FormView editForm = (FormView)ddlCountry.NamingContainer;
if (editForm.DataItem != null)
{
string strCountry = ((DataRowView)editForm.DataItem)["COUNTRY"].ToString();
ddlCountry.ClearSelection();
ListItem li2 = ddlCountry.Items.FindByValue(strCountry);
if (li2 != null) li2.Selected = true;
}
}

protected void ddlRegion_DataBound(object sender, EventArgs e)
{
DropDownList ddlRegion = (DropDownList)sender;
ListItem li = new ListItem("Choose a Region", "");
ddlRegion.Items.Insert(0, li);

FormView editForm = (FormView)ddlRegion.NamingContainer;
if (editForm.DataItem != null)
{
string strRegion = ((DataRowView)editForm.DataItem)["REGION"].ToString();
ddlRegion.ClearSelection();

ListItem li2 = ddlRegion.Items.FindByValue(strRegion);
if (li2 != null) li2.Selected = true;
}

}


8: Don't forget to add this to your Update\Insert parameters on the Objectdatasource for your formview. This is needed to properly find the Region ddl within the Formview

<asp:ControlParameter ControlID="editForm$ddlRegion" Name="Region" />

6 comments:

Anonymous said...

Thanx man, exactly what I was looking for!! Keep on rambling :)

Patt

Brew said...

That works really well, thanks, except my 2nd ddl does not clear the previously loaded listitems. So after selecting a couple of 'Countries' (before inserting form data) I have a very long list of all 'Regions' that have previously shown. Any ideas what I have done wrong?

ipad case said...

wow, thats works great ! really good and detailed btw. thanks for sharing !

Matt Bauer said...

Hi

My name is Matt Bauer and I work for Search Engine Rescue.

We have a couple of business clients who are interested in advertising or guest blog opportunities on your site.

Do you offer either of these? If so, could you forward me details?

Thanks for you help.

Kind regards
Matt


Matt Bauer
Marketing & Partnerships Manager
matt@searchenginerescue.co.uk

Shawn Schneider said...
This comment has been removed by the author.
Shawn Schneider said...

Thanks Brad, this is a great reference! In ddlCountry_DataBound I don't manually select a ListItem because Bind("COUNTRY") handles it, but I do set SelectedValue for ddlRegion because it has no Bind.

I realize Brew's comment is from 2009 but for anyone experiencing his issue, a likely culprit is the AppendDataBoundItems="true" in your asp:DropDownList. I find it useful sometimes but then you must clear the list with code-behind as needed.