通过数据库使用 CascadingDropDown (VB)

作者 :Christian Wenz

下载 PDF

AJAX 控件工具包中的 CascadingDropDown 控件扩展了 DropDownList 控件,以便一个 DropDownList 中的更改将关联值加载到另一个 DropDownList 中。 为此,必须创建一个特殊的 Web 服务。

概述

AJAX 控件工具包中的 CascadingDropDown 控件扩展了 DropDownList 控件,以便一个 DropDownList 中的更改将关联值加载到另一个 DropDownList 中。 (例如,一个列表提供美国各州的列表,然后下一个列表将填充该州的主要城市。) 若要执行此操作,必须创建一个特殊的 Web 服务。

步骤

首先,需要数据源。 此示例使用 AdventureWorks 数据库和 Microsoft SQL Server 2005 Express Edition。 数据库是 Visual Studio 安装 (包括 express edition) 的可选部分,也可在 下 https://go.microsoft.com/fwlink/?LinkId=64064单独下载。 AdventureWorks 数据库是 SQL Server 2005 示例和示例数据库的一部分, () 下载https://www.microsoft.com/download/details.aspx?id=10679。 设置数据库的最简单方法是使用 Microsoft SQL Server Management Studio (/sql/ssms/download-sql-server-management-studio-ssms) 并附加AdventureWorks.mdf数据库文件。

对于此示例,我们假设SQL Server 2005 Express Edition的实例被调用SQLEXPRESS,并且驻留在与 Web 服务器相同的计算机上;这也是默认设置。 如果设置不同,则必须调整数据库的连接信息。

若要激活 ASP.NET AJAX 和 Control Toolkit 的功能, ScriptManager 必须将控件放置在页面上 (但位于 元素) 内的 <form> 任意位置:

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

在下一步中,需要两个 DropDownList 控件。 在此示例中,我们使用 AdventureWorks 中的供应商和联系信息,因此,我们为可用供应商创建一个列表,为可用的联系人创建一个列表:

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

然后,必须将两个 CascadingDropDown 扩展程序添加到页面。 一个 (供应商) 列表中填充第一个供应商,另一个填充第二个 (联系人) 列表。 必须设置以下属性:

  • ServicePath:传递列表条目的 Web 服务的 URL
  • ServiceMethod:传递列表条目的 Web 方法
  • TargetControlID:下拉列表的 ID
  • Category:调用时提交到 Web 方法的类别信息
  • PromptText:从服务器异步加载列表数据时显示的文本
  • ParentControlID: (触发当前列表加载的可选父级下拉列表)

根据所使用的编程语言,有问题的 Web 服务的名称会更改,但所有其他属性值都是相同的。 下面是第一个下拉列表的 CascadingDropDown 元素:

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

第二个列表的控件扩展程序需要设置 属性, ParentControlID 以便选择供应商列表中的条目会触发加载联系人列表中的关联元素。

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

然后,在 Web 服务中完成实际工作,该服务设置如下。 请注意, [ScriptService] 使用 属性,否则 ASP.NET AJAX 无法创建 JavaScript 代理以从客户端脚本代码访问 Web 方法。

<%@ 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

CascadingDropDown 调用的 Web 方法的签名如下所示:

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

因此,返回值必须是由 Control Toolkit 定义的 类型的 CascadingDropDownNameValue 数组。 该方法 GetVendors() 很容易实现:代码连接到 AdventureWorks 数据库,并查询前 25 家供应商。 构造函数中的CascadingDropDownNameValue第一个参数是列表项的描述文字,第二个参数的值 (HTML 元素<option>中的 value 属性) 。 代码如下:

<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

获取供应商的关联联系人 (方法名称: GetContactsForVendor()) 有点复杂。 首先,必须确定在第一个下拉列表中选择的供应商。 Control Toolkit 为该任务定义一个帮助程序方法:该方法 ParseKnownCategoryValuesString() 返回包含 StringDictionary 下拉列表数据的 元素:

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

出于安全原因,必须先验证此数据。 因此,如果由于第一个 CascadingDropDown 元素的 属性设置为 "Vendor") Category 而 (供应商条目,则可能会检索所选供应商的 ID:

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

该方法的其余部分相当简单。 供应商的 ID 用作 SQL 查询的参数,该查询检索该供应商的所有关联联系人。 方法再次返回 类型的 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

加载 ASP.NET 页,过了一会儿,供应商列表将填充 25 个条目。 选择一个条目,并注意第二个下拉列表中如何填充数据。

自动填充第一个列表

第一个列表会自动填充 (单击以查看全尺寸图像)

根据第一个列表中的选定内容填充第二个列表

根据第一个列表中的选定内容填充第二个列表 (单击以查看全尺寸图像)