I'm Mike Pope. I live in the Seattle area. I've been a technical writer and editor
for over 30 years. I'm interested in software, language, music, movies, books, motorcycles,
travel, and ... well, lots of stuff.

The other day I was playing around with how to do cascading drop-down lists using only declarative markup. But as I said then, that works only if you have a straightforward scenario, as in two standalone DropDownList controls just somewhere on the page.

Another common situation is having the drop-down lists inside the template of a data-bound control. I showed an example of an all-declarative drop-down list in a FormView control a while back, but that was just a single drop-down inside the template.

What about cascading drop-down lists inside a template? It can be done, but alas, here we must abandon our effort to use only markup. About pure declarative code, the awesome Polita says:

This specific scenario doesn’t quite work correctly in a FormView control because when the DataSource raises its DataSourceChanged event, the second dropdown list’s Eval statement attempts to evaluate against the container’s (FormView’s) databinding context, which is only valid at DataBind time. Since this happens outside of DataBind time, the context isn’t there and the Eval fails. The best way to work around this is to write some code to manually databind either the second (dependent) dropdown list.

Dang. As Polita told me later, "There are lots of ways to do this." So here's one.

I'll again use the Cars.mdb file. The extremely simplistic schema is this:

CustomersCustomerIDNameManufacturerModel

ManufacturersManufacturers

ModelsModelIDManufacturerModel

We cheat a bit here by not using proper unique IDs and stuff. Bear with me, that's not the interesting part. Here's what we want to accomplish, using a FormView control:

For my example, the FormView control is bound to a data source control for the Customers table; a typical tutorial-type of scenario. The data source control has a Select and an Update command so that we can view and edit data in the FormView control:

What we want is cascading drop-down lists in the EditItemTemplate, as we had in the original, all-declarative FormView example. As in that example, we need data source controls inside the template that the drop-down lists can bind to. The drop-down list for Manufacturer can use declarative markup to bind to the data source control and set its SelectedValue property:

Note that the AutoPostBack property is set to true; more on that in a sec.

It's the second (dependent) drop-down list (Model) where declarative code falls down. As Polita says, there are various ways to handle this. What I did was to go as far as I could declaratively, which meant adding the DropDownList control and a data source control, as with the first drop-down list. However, I did not attempt to set the second DropDownList control's SelectedValue property (which is the property that would normally use Bind or Eval for data binding.) The Select query for the second data source control is parameterized (where Manufacturer = ?), and there's a <parameter> element, but no value is assigned (yet) to the parameter:

Dynamically get the parameter value for the second data source control (from the selected value of the first drop-down list) and then bind the second drop-down list to that data source.

Pass the selected value of the second drop-down list to the FormView control when it's doing an update. (Normally this would be auto-magically handled by a declarative Bind call, but we're not using that for this control).

Update the items in the second drop-down list when the first one changes -- the second list, after all, is dependent on the first. This is why we needed to set AutoPostBack to true for the first drop-down list -- so that it will raise an event we can handle to repopulate the second drop-down list.

Here are the corresponding bits of code. First, the code to dynamically get the parameter value and bind the second drop-down list: