Dependent Drop Downs, Cascading Drop Downs, Filtered Drop Downs.  Whatever you want to call them, this is where you have a secondary drop down list filtered based on the choice from the primary drop down list.  For example:  select a country and you get another drop down list populated with the cities in that country.


This functionality doesn’t seem to be there in WSS 3.0 and/or MOSS 2007. Perhaps I am missing something?  (It wouldn’t be the first time)  But this seems to be fundamental functionality.   Here is some more detail on the scenario:


Country List: I just want a basic drop down list of countries:


City List: I want to filter the cities based on the selected country:


I want a cascading or filtered drop down like so (select Australia, and get a list of Austrlian cities):



Select Germany and get a list of German cities: 


 

Anyway, I couldn’t find a way to do this out of the box, so…I decided to create my own custom field controls to overcome the problem.


I found a couple of useful articles on writing custom field controls.  This article describes how to create a custom drop down list user control along with a custom property page:


http://www.kcdholdings.com/blog/?p=56


I used a lot of code from this example, which has a couple of interesting points.First of all it shows how to create a custom Choice field that can be populated from any list on any site on the web farm (not just the current site). It also has an example of a way to get around the problem of saving custom properties of field controls. For some reason this is not as easy as it should be. I think this will be fixed in SP1. This article describes this problem:


http://www.sharepointblogs.com/ aaronrh/archive/2007/05.aspx


Instead of using a delimited string, I used a class to temporarily store the property values. Here is what my property pages look like for the Parent and Child drop down lists:




Anyway, after learning how to overcome the challenges of field controls in general, it was time to move on to the bigger problem of finding a way to create cascading drop downs. I figured there was hope in the “cross list query” or “caml query”:


http://msdn2.microsoft.com/en- us/library/ms467521.aspx


For example, if I want to filter a list of cities based on a country field in that list:



string caml = @“<WHERE>
                    <EQ>
                       <FIELDREF Name=”{0}” /><VALUE Type=”Text”>{1}</VALUE>
                     </EQ></WHERE>;
SPQuery query = new SPQuery();
query.Query = string.Format(caml, “Country”, “Australia”);
SPListItemCollection results = list.GetItems(query);
this.ChildDropDownList.DataSource = results.GetDataTable();
this.ChildDropDownList.DataTextField = “City”;
this.ChildDropDownList.DataValueField = “City”;
this.ChildDropDownList.DataBind();


So I have a parent drop down list that has a SelectedIndexChanged event, that I use to call a method in the child control that binds to the results of the above query.



void ParentDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
     ChildDropDownListFieldControl child = (ChildDropDownListFieldControl)
               FindControlRecursive(this.Page, “ChildDropDownList”).Parent.Parent;
     child.SetDataSource(ParentDropDownList.SelectedValue);
}


I played around with a lot of different ways to locate the Child drop down list on the page. This is the only one I got to work. (There has to be a better way?)


Anyway, I would appreciate any feedback on any better ways to do this. Here is the source code; I also have a solution file that you can use to install the controls. Just edit the install.bat and point it to the WSS or MOSS site you want to install it on.