Usar CascadingDropDown con una base de datos (VB)

por Christian Wenz

Descargar PDF

El control CascadingDropDown del Kit de herramientas de control de AJAX extiende un control DropDownList para que los cambios en uno de estos controles carguen los valores asociados en otro de estos controles. Para que esto funcione, se debe crear un servicio web especial.

Información general

El control CascadingDropDown del Kit de herramientas de control de AJAX extiende un control DropDownList para que los cambios en uno de estos controles carguen los valores asociados en otro de estos controles. (Por ejemplo, una lista proporciona una lista de estados de EE. UU., y la siguiente lista se rellena con las principales ciudades de ese estado). Para que esto funcione, se debe crear un servicio web especial.

Pasos

En primer lugar, se requiere un origen de datos. En este ejemplo se usa la base de datos AdventureWorks y Microsoft SQL Server 2005 Express Edition. La base de datos es una parte opcional de una instalación de Visual Studio (incluido Express Edition) y también está disponible como una descarga independiente en https://go.microsoft.com/fwlink/?LinkId=64064. La base de datos AdventureWorks forma parte de los ejemplos y bases de datos de ejemplo de SQL Server 2005 (puede descargarla en https://www.microsoft.com/download/details.aspx?id=10679). La manera más fácil de configurar la base de datos es usar Microsoft SQL Server Management Studio (/sql/ssms/download-sql-server-management-studio-ssms) y adjuntar el archivo de base de datos AdventureWorks.mdf.

En este ejemplo, se supone que la instancia de SQL Server 2005 Express Edition se llama SQLEXPRESS y reside en la misma máquina que el servidor web; esta es también la configuración predeterminada. Si la configuración es diferente, tiene que adaptar la información de conexión de la base de datos.

Para activar la funcionalidad de ASP.NET AJAX y el Kit de herramientas de control, el control ScriptManager debe colocarse en cualquier parte de la página (pero dentro del elemento <form>):

<asp:ScriptManager ID="asm" runat="server" />

En el paso siguiente, se requieren dos controles DropDownList. En este ejemplo, usamos la información del proveedor y de contacto de AdventureWorks, por lo que creamos una lista para los proveedores disponibles y otra para los contactos disponibles:

<div>
 Vendor: <asp:DropDownList ID="VendorsList" runat="server"/><br />
 Contacts: <asp:DropDownList ID="ContactsList" runat="server"/><br />
</div>

A continuación, se deben agregar dos controles extensores CascadingDropDown a la página. Una rellena la primera lista (proveedores) y la otra rellena la segunda lista (contactos). Se deben establecer los atributos siguientes:

  • ServicePath: dirección URL de un servicio web que proporciona las entradas de la lista.
  • ServiceMethod: método web que proporciona las entradas de la lista.
  • TargetControlID: identificador de la lista desplegable.
  • Category: información de categoría que se envía al método web cuando se le llama.
  • PromptText: texto que se muestra al cargar datos de lista de forma asincrónica desde el servidor.
  • ParentControlID: (opcional) lista desplegable primaria que desencadena la carga de la lista actual.

Según el lenguaje de programación usado, el nombre del servicio web en cuestión cambia, pero todos los demás valores de atributo permanecen. Este es el elemento CascadingDropDown de la primera lista desplegable:

<ajaxToolkit:CascadingDropDown ID="ccd1" runat="server"
 ServicePath="CascadingDropdown1.vb.asmx" ServiceMethod="GetVendors"
 TargetControlID="VendorsList" Category="Vendor"
 PromptText="Select Vendor" />

Los controles extensores de la segunda lista deben establecer el atributo ParentControlID para que la selección de una entrada en la lista de proveedores desencadene la carga de los elementos asociados en la lista de contactos.

<ajaxToolkit:CascadingDropDown ID="ccd2" runat="server"
 ServicePath="CascadingDropdown1.vb.asmx" ServiceMethod="GetContactsForVendor"
 TargetControlID="ContactsList" ParentControlID="VendorsList"
 Category="Contact"
 PromptText="Select Contact" />

El trabajo real se realiza entonces en el servicio web, que se configura de la manera siguiente. Observe que se usa el atributo [ScriptService]; de lo contrario, ASP.NET AJAX no puede crear el proxy de JavaScript para acceder a los métodos web desde el código de script del lado cliente.

<%@ WebService Language="VB" Class="CascadingDropdown1" %>
Imports System.Web.Script.Services
Imports AjaxControlToolkit
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.Data.SqlClient
<ScriptService()> _
Public Class CascadingDropdown1
 Inherits System.Web.Services.WebService
 ' ...
End Class

La firma de los métodos web a los que llama CascadingDropDown es la siguiente:

Public Function MethodNameHere(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue()

Por lo tanto, el valor devuelto debe ser una matriz de tipo CascadingDropDownNameValue definida por el Kit de herramientas de control. El método GetVendors() es bastante fácil de implementar: el código se conecta a la base de datos AdventureWorks y consulta los primeros 25 proveedores. El primer parámetro del constructor CascadingDropDownNameValue es el título de la entrada de lista, el segundo su valor (atributo value en el elemento HTML option<>). Este es el código:

<WebMethod()> _
Public Function GetVendors(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue()
 Dim conn As New SqlConnection("server=(local)\SQLEXPRESS; Integrated Security=true; Initial Catalog=AdventureWorks")
 conn.Open()
 Dim comm As New SqlCommand( _
 "SELECT TOP 25 VendorID, Name FROM Purchasing.Vendor", conn)
 Dim dr As SqlDataReader = comm.ExecuteReader()
 Dim l As New List(Of CascadingDropDownNameValue)
 While (dr.Read())
 l.Add(New CascadingDropDownNameValue(dr("Name").ToString(),dr("VendorID").ToString()))
 End While
 conn.Close()
 Return l.ToArray()
End Function

Obtener los contactos asociados de un proveedor (nombre de método GetContactsForVendor()) es un poco más complicado. En primer lugar, se debe determinar el proveedor que se ha seleccionado en la primera lista desplegable. El Kit de herramientas de control define un método auxiliar para esa tarea: el método ParseKnownCategoryValuesString() devuelve un elemento StringDictionary con los datos desplegables:

<WebMethod()> _
Public Function GetContactsForVendor(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue()
 Dim VendorID As Integer
 CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues)

Por motivos de seguridad, estos datos deben validarse primero. Por lo tanto, si hay una entrada Vendor (porque la propiedad Category del primer elemento CascadingDropDown está establecida en "Vendor"), se puede recuperar el identificador del proveedor seleccionado:

If Not kv.ContainsKey("Vendor") Or Not Int32.TryParse(kv("Vendor"),VendorID) Then
 Throw New ArgumentException("Couldn't find vendor.")
 End If

Por tanto, el resto del método es bastante sencillo. El identificador del proveedor se usa como parámetro para una consulta SQL que recupera todos los contactos asociados a ese proveedor. Una vez más, el método devuelve una matriz de tipo CascadingDropDownNameValue.

Dim conn As New SqlConnection("server=(local)\SQLEXPRESS; Integrated Security=true; Initial Catalog=AdventureWorks")
 conn.Open()
 Dim comm As New SqlCommand("SELECT Person.Contact.ContactID, FirstName, LastName FROM Person.Contact,Purchasing.VendorContact WHERE VendorID=@VendorID AND Person.Contact.ContactID=Purchasing.VendorContact.ContactID",conn)
 comm.Parameters.AddWithValue("@VendorID", VendorID)
 Dim dr As SqlDataReader = comm.ExecuteReader()
 Dim l As New List(Of CascadingDropDownNameValue)
 While (dr.Read())
 l.Add(New CascadingDropDownNameValue(dr("FirstName").ToString() & " " & dr("LastName").ToString(),dr("ContactID").ToString()))
 End While
 conn.Close()
 Return l.ToArray()
End Function

Cargue la página ASP.NET y, después de un corto tiempo, la lista de proveedores se rellena con 25 entradas. Elija una entrada y observe cómo la segunda lista desplegable se rellena con datos.

The first list is filled automatically

La primera lista se rellena automáticamente (haga clic para ver la imagen a tamaño completo).

The second list is filled according to the selection in the first list

La segunda lista se rellena según la selección de la primera lista (haga clic para ver la imagen a tamaño completo).