WEBSWAPP Silverlight ASP.NET 3.5 ASP.NET 2.0 ASP.NET 1.0
Cascading Lists
AJAX ToolKit
Hierarchies
C#-ListView C#-GridView UpdatePanel

Cascading Dropdownlists within a ListView using LINQ

    
Suite#:
Address Line 1: 3522 Bloomington Rd.vn
Address Line 2:
Location: Lansing , Michigan, United States
Postal Code: 48155fd
Address Type: Billing
Insert new contact address
Suite#:
Address Line 1:  
Address Line 2:
Location:

Postal Code:
Address Type:

You are most likely reading this article because you got one of the following errors while attempting to bind the values selected from cascading lists to the context data record of a templated server control:

  1. Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control
  2. 'DropDownList1' has a SelectedValue which is invalid because it does not exist in the list of items.

The problem is that you are attempting to bind to a dependent dropdown list a value from its container’s data context when the latter was not bound to the container. The container is the ListView in this demo. Its data context is the address record that you are attempting to Edit or Insert.

In this example, a change in the country dropdown list selection causes the datasource for the province’s list to retrieve a list of provinces specific to that country selection. This does not cause a problem. The problem appears when you have a BIND statement that attempts to bind the selectedvalue of the province dropdown list to a property on the address object, e.g. SelectedValue='<%#Bind("provinceId") %>'. However the postback (triggered by the country's selection change) did not re-bind the container (the ListView) to its data context (the address object) rather the container's template was rendered from the saved viewstate. Therefore you get the error that informs you that you cannot use BIND on a control that is not databound to its data context.

There are two ways to deal with the problem; you can either try a technical workaround to remove the 2-way databinding from the cascading dropdownlists and replace it with customized code during processing the ItemUpdating event as I did in this demo in ASP.NET 2.0., or you can change the way you look at the data in a cascading relationship.

Why do you have to save the values of all the members of the cascading relationship (e.g. country id, province Id, city id) to the address object? We can design the data such as the City record would have a unique Id that can identify the remaining elements of the cascade. For example a record for London, Ontario, Canada would have a CityId different from a record for London, England, UK.

In this demo, I use a SQL database whose structure is represented by the following Schema in which the hierarchical country-province-city relation is stored in one table named Location. The parentId of each location record points to the Id of another location record (self-join). Therefore the primary key Id of the City is enough to identify the province and the country.

This strategy avoids running into the problem caused by the BIND statement. In this demo, I delegate the function of selecting the elements in the cascading relationship to a web user control. The wucCity.ascx exposes a public property named CityId which I "Bind" to my address record.

To improve the user experience I add several AJAX features to this ListView in this UpdatePanel Demo

The sample demo that Microsoft presented in its AJAX Toolkit CascadingDropDown sample used a case where the color for a particular car make-model does not necessarily have to be a unique data record, i.e. the green color record is not unique to Acura-Integra, it can also be a color selection for Audi-A6. Therefore a car's record saves all three values (car make, model and color). The 3 keys represent a unique identifier to be able to retrieve the cascading relationship that the user specified. But if we were to change this relationship such as the green color record for Acura-Integra has an Id that is different from the green color record for Audi-A6 then we do not need to save the user selection of the car make and model. We can use the color record selection to identify both the car make and model.

On this thread you will find an exchange between me and one of Microsoft team who argued with me over this solution. You might want to verify his argument for yourself.

Source code:

C#-ListView source code wucAddressType.ascx wucCity.ascx