CascadingDropDown

Descripción

Imaginemos un escenario en que tenemos 3 listas desplegables. La primera de ellas tiene unos items determinados, pero la segunda lista depende del valor que se le dé a la primera y la tercera lista del valor que se le dé a la segunda.

Hasta ahora teníamos dos opciones:
- Implementar una compleja serie de funciones javascript,
- Utilizar ASP.NET recargando las páginas.

En el primer caso quedaba muy profesional de cara al cliente, pues éste manejaba muchos datos de forma muy rápida y sin recargar la página... sin embargo era muy poco profesional del cara al programador pues la complejidad en el javascript se incrementaba exponencialmente.

En el segundo caso el programador conseguía una programa estable, rápido y fácilmente modificable, pero el usuario veía cómo se recargaba la página entera cada vez que elegía una opción diferente.

Pues bien, con el CascadingDropDown solucionamos los problemas y nos quedamos con las ventajas: no se recargará la página y se definirá el contenido de los DropDownList mediante ASP.NET

Propiedades

• TargetControlID: el ID de la lista desplegable a la que se aplicará.
• Category: se define como el nombre de la categoría que la lista desplegable representa. Su utilidad será la de representar uno de los dos parámetros de entrada al ServiceMethod que estudiaremos posteriormente
• PromptText: es un texto opcional que verá el usuario cuando la lista desplegable esté vacía.
• LoadingText: también es un texto opcional que verá el usuario cuando el dato se está cargando.
• ServicePath: define el path del servicio web que devuelve la información que se usará para rellenar la lista desplegable. Si el servicio web se encuentra en la propia página en que estamos trabajando, no pondremos nada en esta propiedad.
• ServiceMethod: le dedicamos un apartado exclusivo
• ParentControlID: ID de la lista desplegable de cuya selección depende esta lista desplegable. En nuestro ejemplo, si esta es la lista desplegable 2, el ParentControlID apuntaría a la lista desplegable 2. Gracias a ParentControlId creamos una jerarquía de listas desplegables. En caso de estar en lo más alto de la jerarquía no pondríamos nada.
• SelectedValue: valor que vendría seleccionado por defecto. Es opcional.

ServiceMethod

El es la función a la que se llamará para rellenar la lista desplegable. Tendrá el siguiente aspecto:

[WebMethod]
public CascadingDropDownNameValue[] GetDropDownContents(string knownCategoryValues, string category){...}

...donde lo único que se podrá cambiar será el nombre de la función, pues el resto debe ser igual.

Observamos que:
• La función debe ir precedida por [WebMethod].
• CascadingDropDownNameValue es un tipo de dato dentro del namespace AjaxControlToolkit (que en nuestro ejemplo suponemos ya importado mediante using (C#) o import (VB)).
• El segundo parámetro (category) se corresponde con el atributo Category que hemos indicado en nuestro control CascadingDropDown.

Mención especial merece el primer parámetro. En éste se almacena el valor seleccionado de cada una de las listas desplegables predecesoras en la jerarquía. Siguiendo con nuestro ejemplo, si estuviéramos dentro del definido en la lista desplegable 3, el contenido del primer parámetro sería similar a:

Category1:valor1;category2:valor2

Pero no cabe asustarse, no hace falta que parseemos a mano esa información, pues dispondemos del método ParseKnownCategoryValuesString que hará ese trabajo por nosotros, de modo que haciendo:

StringDictionary knownCategoryValuesDictionary = AjaxControlToolkit .CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

... obtenemos un StringDictionary bien ordenado y sencillo de utilizar.

Ejemplo

Nota 1: hay que importar los siguientes namespaces:
- System.Web.Services
- AjaxControlToolkit
- System.Collections.Specialized
Nota 2: EnableEventValidation debe valer false

El uso avanzado del CascadingDropDownList implica un estudio más en profundidad de todas sus características. En los diferentes blogs tecnológicos encontramos diferentes ejemplos en los que se configura la fuente de datos de diferentes listas desplegables mediante XML o ases de datos. Nosotros mostramos un sencillo ejemplo para que el lector se agilice en el uso del CascadingDropDown y pueda acceder a ejemplos mucho más complejos.

Nuestro ejemplo consta de dos listas desplegables, donde la segunda depende de la primera. En el momento hacemos una selección en la primera lista desplegable el mecanismo del CascadingDropDown entra en funcionamiento y se rellena la segunda lista desplegable sin que la página se recargue.

CascadingDropDown.aspx
<atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
</atlas:ScriptManager>

<asp:DropDownList ID="DropDownList1" runat="server">
<asp:ListItem Text="Elige tu humor y te aconsejaré tu color" Value="-1">
</asp:ListItem>
<asp:ListItem Text="Triste" Value="Triste">
</asp:ListItem>
<asp:ListItem Text="Alegre" Value="Alegre">
</asp:ListItem>
</asp:DropDownList>

<br />

<asp:DropDownList ID="DropDownList2" runat="server">
</asp:DropDownList>

<br />

<ajaxToolkit:CascadingDropDown ID="CascadingDropDown2" runat="server"
TargetControlID="DropDownList2"
Category="color"
ServiceMethod=""
ParentControlID="DropDownList1">
</ajaxToolkit:CascadingDropDown>

CascadingDropDown.aspx.cs
[WebMethod]
public CascadingDropDownNameValue[] (string knownCategoryValues, string category)
{
CascadingDropDownNameValue[] respuesta = new AjaxControlToolkit .CascadingDropDownNameValue[2];

if (category == "color")
{
StringDictionary knownCategoryValuesDictionary = AjaxControlToolkit .CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

if (DropDownList1.SelectedValue != "-1")
{
if (DropDownList1.SelectedValue == "Alegre")
{
respuesta[0] = new CascadingDropDownNameValue("Amarillo", "Amarillo");
respuesta[1] = new CascadingDropDownNameValue("Naranja", "Naranja");
}
else if (DropDownList1.SelectedValue == "Triste")
{
respuesta[0] = new CascadingDropDownNameValue("Gris", "Gris");
respuesta[1] = new CascadingDropDownNameValue("Azul marino", "Azul_marino");
}
}
}

return respuesta;
}