作者 :克里斯蒂安·温茨
AJAX 控件工具包中的级联DropDown 控件扩展了 DropDownList 控件,以便一个 DropDownList 中的更改加载另一个 DropDownList 中的关联值。 若要执行此操作,必须创建一个特殊的 Web 服务。
概述
AJAX 控件工具包中的级联DropDown 控件扩展了 DropDownList 控件,以便一个 DropDownList 中的更改加载另一个 DropDownList 中的关联值。 (例如,一个列表提供美国州的列表,然后下一个列表填充该州的主要城市。若要执行此操作,必须创建一个特殊的 Web 服务。
步骤
首先,需要数据源。 此示例使用 AdventureWorks 数据库和 Microsoft SQL Server 2005 Express Edition。 该数据库是 Visual Studio 安装(包括 Express 版)的可选部分,也可以单独下载 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 数据库文件。
对于此示例,我们假定调用 SQLEXPRESS SQL Server 2005 Express Edition 的实例并驻留在 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> 值属性)。 代码如下:
<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)
出于安全原因,必须先验证此数据。 因此,如果有 Vendor 条目(因为 Category 第一个 CascadingDropDown 元素的属性已设置为 "Vendor"),则可能会检索所选供应商的 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 个条目。 选择一个条目并注意第二个下拉列表中填充数据的方式。
自动填充第一个列表(单击以查看全尺寸图像)
第二个列表根据第一个列表中的选定内容填充(单击以查看全尺寸图像)