WEBSWAPP Silverlight ASP.NET 3.5 ASP.NET 2.0 ASP.NET 1.0
Cascading Lists
ITemplate
DDL in GridView
G/V MultiSelect
Nested GridViews
RegExp
DataGrid Reorder
Events fire twice
Hyperlink Field
TextBox
UpdateParameters
MultiView
TreeView
C#-FormView VB-FormView C#-GridView VB-GridView C#-DetailsView VB-DataList

Demo for 2-way databinding cascading lists within a GridView

CommandsCompany NameStreet AddressCountryProvinceCity
Edit WEBSWAPP Development Inc. 3070 Guildford Way Canada British Columbia Coquitlam
Edit MultiMedia CanStirr FlipFlop 277- 5 th street United States Florida Hollywood
Edit SugarPlumPrincess Kids Toys 25 Edward Ave. United Kingdom Scottland Dublin
Edit Frisian fishermen Ltd 252 Frisian Street North Netherlands North Holland Enkhuizen
Edit Seveso Bank 782 Leonardo da Vinci Ave. Italy Basilicata Potenza

You might have wanted to use inside a databound templated server control (e.g. the FormView or the GridView) several cascading dropdownlists. The System.Web.UI.WebControls.ListItems in each dropdownlist would change based on the selection of the previous dropdownlist, e.g. the city selections would change based on the province and the latter would change based on the country selection. Sounds easy? Well, you added to your webform a datasource object linked for each dropdownlist where the SelectParameters collection contains a ControlParameter pointing to the previous list.

But you encounter any of those 2 error messages:

  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 it was not bound to the container. The container is the FormView or GridView 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 FormView or the GridView) 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, or you can change the way you look at the data in a cascading relationship, which I present in this ASP.NET 3.5 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.

In this demo I deal with a case where you are able to save all values of the cascading relationship on the same record by handling the ItemUpdating and ItemInserting events instead of using the 2-way databinding method BIND. But in this ASP.NET 3.5 ListView demo I present the strategy that allows you to save the cascading relationship by saving only the id of the record at the lowest level of the cascading relationhsip (in this case it is the CityId)

If you are still getting the message that:

'DropDownList1' has a SelectedValue which is invalid because it does not exist in the list of items.

then since you are using Bind (which will set the selected value from the data as well as save the selected value to data upon update), the dropdownlist must be populated with all possible values.

The solutions are

  1. if the problem is happening due to Null values in databound field then you can declare the dropdownlist with a null item at top while setting the AppendDataBoundItems property to true so that items are appended to (instead of replacing) the null item, like this

    <asp:DropDownList ID="ddlCountry" runat="server

    AppendDataBoundItems=true

    DataSourceID="odsCountries" AutoPostBack="True"

    SelectedValue='<%# Bind("Country") %>'>

          <asp:ListItem Value="">Select an Item</asp:ListItem>

    </asp:DropDownList>

     

    For more information on the usage of the AppenDataBoundItems property refer to the MSDN: http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.appenddatabounditems(VS.80).aspx

     

  2. if the problem is happening due to illegal values saved in the databound field (that are not part of the set of values displayed on the dropdownlist) then you can:
    1. fix the data on the database
    2. create a join query within the objectdatasource for dropdownlist that would bring not only the legal values for this list but also any illegal values in the databound field
    3. handle it on the level of the user interface like I did on my sample where I removed the Bind statement from the DropDownList and replaced with code within the dropdownlist.DataBound and the GridViewRowUpdating events

Source code:

C#-GridView source code