Freigeben über


The Toolkit in action: Hooking up the CasdcadingDropDown

The "Atlas" Control Toolkit makes it super easy to add great usability features to your website. 

One of the things people regularly want to do is to create a "cascading" set of DropDownLists, where the value of each populates the values below.  The "Atlas" Control Toolkit contains a great extender to make this super easy to set up.  It does all of the population of the lists using an async call to a web service, which allows you to filter and cache the data on the server side and easily integrate it into your page. 

Go here to download and install the toolkit, and the Atlas April CTP if you don't already have it.  Once you've got it installed, you can see demos of all the controls in the toolkit.  Note that, like Atlas, this toolkit is an early version.  If you find issues, please report them in the Atlas Toolkit Forum so we can fix them for the next release.

But say I want to hook up a set of drop down lists.  First, I create a new Atlas Website, and add a reference to the toolkit assembly.  You'll find the assembly (called AtlasControlTookit.dll) in the "AtlasControlToolkit\bin" directory where you installed the tookit.  When prompted to replace the "Microsoft.Web.Atlas.DLL", choose 'No'.

In the default.aspx page and add some dropdowns to it:

   <div> ns="urn:schemas-microsoft-com:office:office" prefix="o" ?>

    Make: <asp:DropDownList ID="ddlMake" runat="server"/><br/>

    Model: <asp:DropDownList ID="ddlModel" runat="server"/><br/>

    Color: <asp:DropDownList ID="ddlColor" runat="server"/>

    <br />

    <asp:Button ID="Button1" runat="server" Text="Submit" />

   </div>

Now, at the top of your ASPX page, register a prefix for the reference to the tookit:

<%@ Register Assembly="AtlasControlToolkit" Namespace="AtlasControlToolkit" TagPrefix="atlasToolkit" %>

And then add the extender itself:

 

<atlasToolkit:CascadingDropDown ID="CascadingDropDown1" runat="server">

</atlasToolkit:CascadingDropDown>

At runtime, the extender will make callbacks to a web service we specify.  In that web service, it expects a WebMethod with the following signature (note that parameter names must match too!):

[WebMethod]

public CascadingDropDownNameValue[] GetColorsForModel(string knownCategoryValues, string category)

The knownCategoryValues parameter will return a string containing the currently selected category values, as well as the category to retrieve values for.  For example, if the extender is populating the "Color" field, you will be passed the values for the "Make" and "Model" fields, as well as "Color" to specify the field to return values for.

The CascadingDropDown class has a helper method for unpacking the category values:

StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

This method will return a StringDictionary containing the name/value pairs of the currently selected values.  So imagine you've got a database with tables for the Make (manufacturer), Model, and Color information, and you're accessing that database through a DataSet to which you've added methods for getting each set of values.

The web method to get the available colors for a given model would look like this:

[WebMethod]

public CascadingDropDownNameValue[] GetColorsForModel(

string knownCategoryValues, string category) {

 

      StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

 

      int modelId;

 

      if (!kv.ContainsKey("Model") || !Int32.TryParse(kv["Model"], out modelId))

      {

      throw new ArgumentException("Couldn't find make.");

      }

 

      CarsTableAdapters.ColorTableAdapter adapter = new

CarsTableAdapters.ColorTableAdapter();

 

      Cars.ColorDataTable colorTable = adapter.GetColorsForModel(modelId);

 

List<CascadingDropDownNameValue> values = new

List<CascadingDropDownNameValue>();

 

      foreach (DataRow dr in colorTable) {

          values.Add(

new CascadingDropDownNameValue(

(string)dr["Color"],

dr["ColorID"].ToString()));

      }

 

      return values.ToArray();

}

So it's simple to return the values.  Now let's hook up our extender:

<atlasToolkit:CascadingDropDown ID="CascadingDropDown1" runat="server">

    <atlasToolkit:CascadingDropDownProperties

TargetControlID="ddlMake"

Category="Make"

PromptText="Select a manufacturer"

ServicePath="CarsService.asmx"

ServiceMethod="GetCarMakes" />

</atlasToolkit:CascadingDropDown>

If you look at this it's pretty simple.  TargetControlID specifies which control we're extending, in this case it's the drop down that specifies the manufacturer or "make" of the car.  PromptText specifies the text to show in the dropdown when no value is selected, and the ServicePath and ServiceMethod attributes tell the extender which web service to call to fetch it's values.

We can also do this hook up from the designer.  If you switch to design view, and select the "ddlModel" DropDownList, you can make these hookups in the property browser at design time:

Note the "ParentControlID" property which specifies which DropDownList is the "parent" for this one.  By setting these parent values, you can chain or "cascade" these values, and the CascadingDropDown extender will automatically manage setting, clearing, and loading the data for you. 

If you set up the ddlModel and ddlColor lists as well and go back to source view, you'll see:

        <atlasToolkit:CascadingDropDown ID="CascadingDropDown1" runat="server">

            <atlasToolkit:CascadingDropDownProperties

TargetControlID="ddlMake"

Category="Make"

PromptText="Select a manufacturer"

ServicePath="CarsService.asmx"

ServiceMethod="GetCarMakes" />

          

            <atlasToolkit:CascadingDropDownProperties

TargetControlID="ddlModel"

ParentControlID="ddlMake"

PromptText="Please select a model"

ServiceMethod="GetModelsForMake"

                ServicePath="CarsService.asmx"

Category="Model" />

 

<atlasToolkit:CascadingDropDownProperties

TargetControlID="ddlColor"

ParentControlID="ddlModel"

PromptText="Please select a color"

ServiceMethod="GetColorsForModel"

ServicePath="CarsService.asmx"

Category="Color"/>

          

        </atlasToolkit:CascadingDropDown>

Once you've completed your web service methods, your cascading drop down is complete!

Finally, in order for the values to be submitted, EventValidation needs to be disabled for the page.  EventValidation ensures that the values in each control match the values that were present when the page was rendered, but since these drop downs are populating on the client side, this is never true.  We’re working on a way to resolve this issue (I'm not happy about it either!), but please ensure that you understand this and validate the data appropriately in your post back when using this control.

pbrs.png

Comments

  • Anonymous
    April 14, 2006
    Thanks for the example -

    How do I call methods on the page itself that are defined as web methods?
  • Anonymous
    April 14, 2006
    We've added that for the second release.  If you want to modify the code yourself, the major change is in CascadingDropDownBehavior.js.  Search for "Sys.Net.ServiceMethod" and then wrap that call like:

    if (_servicePath) {
        Sys.Net.ServiceMethod.invoke(...);
    }
    else {
     // Call the helper web service
               Sys.Net.PageMethod.invoke(
                   _serviceMethod,                
                   { 'knownCategoryValues' : knownCategoryValues, 'category' : _category },
                   Function.createDelegate(this, _onMethodComplete),
                   Function.createDelegate(this, _onMethodTimeout),
                   Function.createDelegate(this, _onMethodError),
                   Function.createDelegate(this, _onMethodAborted),
                   this
               );
    }

    And in CascadingDropDownProperties.EnsureValid, remove "stringServicePath" from the list.  Now if you specify a page method and no service path, it'll work.

  • Anonymous
    April 17, 2006
    Two questions:

    1. Will the CascadingDropDown extender work with a custom control that derives from DropDownList and leaves off the SupportsEventValidation attribute? That way EventValidation would not have to be disabled at the page or even application level. It would effectively be disabled just at the control level.

    2. Does disabling event validation at the page level interfere with the functioning of the standard ASP.NET validation controls?
  • Anonymous
    April 17, 2006
    Answers for dli

    1) No it won't - the behavior relies on the events and properties present on the client OPTION element.

    2) It won't break anything.  Event validation makes sure that the data that comes back is expected.  It's a security feature to prevent people from spoofing calls to your site by sending bogus even postbacks.  So if you do this, you need to make sure you validate the data on the server side.
  • Anonymous
    April 19, 2006
    Cool MSDN ASP.NET 2.0 GridView Control
    Article [Via: Scott Guthrie ]
    How to Link Stylesheets from...
  • Anonymous
    April 19, 2006
    Today I finally managed to download a non-corrupted version of the April Atlas CTP installer, and I now...
  • Anonymous
    May 03, 2006

      I think that all that you posted is really good but I've been improving on comparison between AjaxPro.NET vs Atlas technologies, and I have a question. Are you sure what are you sending when you causes a POST to a server?
      Using Sys.Net.ServiceMethod.invoke sentence you only sends a JSON data, but when you use a PageMathods sentence, you are sending ALL THE PAGE to the server.
      To make sure of that you can use IE HTTP Analyzer or Fiddler application
     
      This is a very important issue because in AjaxPro.NET all post that you cause to the server you are sending only JSON data and no more.

      I don't know why Microsoft ONLY USE web services to comunicate to server as a efficiently way. Why I can't communicate whit any WebMethod on any class like AjaxPro.NET??

      I like A lot Atlas because is a big Framework integrated on VS2005, and makes more easy development, but I think that there are very important issues that have not been resolved yet.

      Thanks!!!

       See you soon!!!
  • Anonymous
    May 05, 2006
    Earlier this week we released the April CTP refresh of Atlas (which, like the March CTP drop, supports...
  • Anonymous
    May 21, 2006
    Earlier this week we released the April CTP refresh of Atlas (which, like the March CTP drop, supports...
  • Anonymous
    June 01, 2006
    Works! but CascadingDropDown.TargetProperties(n).SelectedValue= Nothing

    Hi,
    I've found this article very useful and managed to build a cascading dropdown for my webapp using 6 realated dropdowns that previously I needed to do a series of postbacks.  I think I may be missing part of trhe concept though, when i try to access the inner dropdowns selcted values OR the cascadingdropdown.targetproperties.selectedvalues, I find that these are Nothing rather than the selected text.
    I have not wrapped the cascadingdropdown in an update panel or a formview control, am I missing something out?
    Any help would be greatly appreaciated
  • Anonymous
    June 16, 2009
    PingBack from http://lowcostcarinsurances.info/story.php?id=3766