使用CascadingDropDown控件和数据库

Christian Wenz

本文档是Visual Basic 教程(转至 Visual C# 教程

AJAX Control Toolkit 中的 CascadingDropDown 控件扩展了 DropDownList 控件 , 从而当一个 DropDownList 发生变化时可在另一个 DropDownList 中加载相关的值。为了实现这个目的,必须创建一个特殊的 Web 服务。

« 前一篇教程 |  下一篇教程 »

概述

AJAX Control Toolkit 中的CascadingDropDown 控件扩展了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 Samples 和Sample Databases

(在此处下载:https://www.microsoft.com/downloads/details.aspx?FamilyID=e719ecf7-9f46-4312-af89-6ad8702e4e6e&DisplayLang=en

的一部分。

配置该数据库的最简单的方法是,使用Microsoft SQL Server Management Studio Express (https://www.microsoft.com/downloads/details.aspx?FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796&DisplayLang=en) ,

附加 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()

如此 ,返回值必须是一个CascadingDropDownNameValue类型 (Control Toolkit 定义了该类型 )的数组。

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)

为了安全起见 ,首先应该验证该数据。

这样 ,如果有一个Vendor 项 (因为第一个CascadingDropDown 元素的Category 属性设置为了"Vendor"),

就可检索出所选供应商的ID:

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

该方法的其余部分比较易懂。SQL查询用所选供应商的ID 作为参数来检索该供应商的所有相关联系人。

该方法再次返回一个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 条列表项。

从中选择一项,留意看第二个下拉列表怎样填充了数据。

自动添充第一个列表

根据第一个列表中的选择来填充第二个列表

 

 

下一篇教程