通过数据库使用 CascadingDropDown (C#)

作者 :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.cs.asmx" ServiceMethod="GetVendors"
 TargetControlID="VendorsList" Category="Vendor"
 PromptText="Select Vendor" />

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

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

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

<%@ WebService Language="C#" Class="CascadingDropdown1" %>
using System.Web.Script.Services;
using AjaxControlToolkit;
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data.SqlClient;
[ScriptService]
public class CascadingDropdown1 : System.Web.Services.WebService
{
 // ...
}

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

public CascadingDropDownNameValue[] MethodNameHere(string knownCategoryValues, 
    string category)

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

[WebMethod]
public CascadingDropDownNameValue[] GetVendors(string knownCategoryValues, string category)
{
    SqlConnection conn = new SqlConnection("server=(local)\\SQLEXPRESS; 
    Integrated Security=true; Initial Catalog=AdventureWorks");
    conn.Open();
    SqlCommand comm = new SqlCommand("SELECT TOP 25 VendorID, Name 
    FROM Purchasing.Vendor",conn);
    SqlDataReader dr = comm.ExecuteReader();
    List<CascadingDropDownNameValue> l = new List<CascadingDropDownNameValue>();
    while (dr.Read())
    {
        l.Add(new CascadingDropDownNameValue(dr["Name"].ToString(),
        dr["VendorID"].ToString()));
    }
    conn.Close();
    return l.ToArray();
}

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

[WebMethod]
public CascadingDropDownNameValue[] GetContactsForVendor(string knownCategoryValues, 
    string category)
{
    int VendorID;
    CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

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

if (!kv.ContainsKey("Vendor") || !Int32.TryParse(kv["Vendor"],out VendorID)) 
{
    throw new ArgumentException("Couldn't find vendor.");
};

那么,该方法的其余部分相当简单。 供应商的 ID 用作 SQL 查询的参数,该查询检索该供应商的所有关联联系人。 方法再次返回 类型 CascadingDropDownNameValue为 的数组。

SqlConnection conn = new SqlConnection("server=(local)\\SQLEXPRESS; 
 Integrated Security=true; Initial Catalog=AdventureWorks");
 conn.Open();
 SqlCommand comm = 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);
 SqlDataReader dr = comm.ExecuteReader();
 List<CascadingDropDownNameValue> l = new List<CascadingDropDownNameValue>();
 while (dr.Read())
 {
 l.Add(new CascadingDropDownNameValue(
 dr["FirstName"].ToString() + " " + dr["LastName"].ToString(),
 dr["ContactID"].ToString()));
 }
 conn.Close();
 return l.ToArray();
}

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

自动填充第一个列表

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

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

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