简单三层+AJAX Control Toolkit实现dropdownlist无刷新联动

这篇文章肯定有不足的地方,希望大家指正。谢谢
另外平台是VS2005+SQL2000/2005

参考信息:
1,微软官方Using CascadingDropDown with a Database文档:http://www.asp.net/AJAX/AjaxControlToolkit/Samples/Walkthrough/CCDWithDB.aspx
2,使用SQL Server对CascadingDropDown进行填充 http://blog.csdn.net/chen_cxb/archive/2008/03/05/2148565.aspx
by conan304 2009年6月6日16:11:33

一:前期准备工作
1,AJAX的安装
请参考微软的asp.net ajax页面:http://www.asp.net/AJAX/
a,ASP.NET 2.0 AJAX Extensions 1.0 
      下载页面:http://www.asp.net/ajax/downloads/archive/
      具体下载地址:ASP.NET 2.0 AJAX Extensions 1.0 点击下载
说明:页面上有ASP.NET 2.0 AJAX Extensions 1.0 Source Code可以下载。
安装:下载后双击运行安装。

b,AJAX Control Toolkit 的安装。
注意:因为平台是VS2005,所以请下载1.0.
下载页面:点击打开AJAX Control Toolkit Version 1.0.20229下载页面
具体下载地址(包含源代码):点击下载AJAX Control Toolkit 1.Version 1.0.20229(包含源代码)
安装:解压之后拷贝\AjaxControlToolkit\SampleWebSite\Bin\AjaxControlToolkit.dll 到所建ajax网站个bin目录下,添加AjaxControlToolkit.dll的引用。
工具箱安装:建立ajax网站之后,右键工具箱--添加选项卡--AJAX Control Toolkit--选择项--浏览--找到 AjaxControlToolkit.dll 双击,确定就OK。

c,数据库
下载全国省市区数据库信息(SQL2005),然后附加。
下载地址:https://files.cnblogs.com/conan304/area.zip

二页面设计、代码。
1,数据库的三个存储过程,分别得到省、市、区县信息。很简单。

USE [area]
GO
/****** 对象:  StoredProcedure [dbo].[proc_getProvince]    脚本日期: 06/06/2009 16:58:48 ******/
/****** 得到省份信息 ******/
/****** by Conan304 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create procedure [dbo].[proc_getProvince]
as
begin
    
select province,provinceid from dbo.province
    
order by [id]
end
GO
/****** 对象:  StoredProcedure [dbo].[proc_getCity]    脚本日期: 06/06/2009 16:58:48 ******/
/****** 得到城市信息 ******/
/****** by Conan304 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create procedure [dbo].[proc_getCity]
(
    
@provinceid varchar(20)
)
as
begin
    
select city,cityid from dbo.city    
    
where father=@provinceid
    
order by [id]
end
GO
/****** 对象:  StoredProcedure [dbo].[proc_getArea]    脚本日期: 06/06/2009 16:58:47 ******/
/****** 得到区县信息 ******/
/****** by Conan304 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create procedure [dbo].[proc_getArea]
(
    
@cityid varchar(20)
)
as
begin
    
select area,areaid from dbo.area    
    
where father=@cityID
    
order by [id]
end
GO

2,建立DAL层。
简单的代码:

public class SQLHelper
    {        
        
private readonly string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["SqlConnectionString"].ToString().Trim();        

        
private SqlConnection conn;

        
#region 打开数据库连接
        
/// <summary>
        
/// 打开数据库连接
        
/// </summary>
        private void openDataBase()
        {
            
if (conn == null)
            {
                conn 
= new SqlConnection();
                conn.ConnectionString 
= connectionString;
            }
            
if (conn.State != ConnectionState.Open)
            {
                conn.Open();
            }
        }
        
#endregion

        
#region 关闭数据库连接
        
/// <summary>
        
/// 关闭数据库连接
        
/// </summary>
        private void closeDatabase()
        {
            
if (conn == null)
            {
                
return;
            }
            
else
            {
                
if (conn.State != ConnectionState.Closed)
                {
                    conn.Close();
                }
            }
        }
        
#endregion

        
#region 执行存储过程返回DataSet
        
/// <summary>
        
/// 执行存储过程返回DataSet
        
/// </summary>
        
/// <param name="procName">存储过程名</param>
        
/// <param name="param">参数</param>
        
/// <returns></returns>
        public DataSet getDataSetExecProc(string procName, SqlParameter[] param)
        {
            DataSet ds 
= new DataSet();
            
try
            {
                
this.openDataBase();
                SqlCommand cmd 
= new SqlCommand();
                cmd 
= conn.CreateCommand();
                cmd.CommandText 
= procName;
                cmd.CommandType 
= CommandType.StoredProcedure;
                cmd.CommandTimeout 
= 30;
                SqlDataAdapter da 
= new SqlDataAdapter();
                da.SelectCommand 
= cmd;
                
if (param != null)
                {
                    
foreach (SqlParameter sqlparam in param)
                    {
                        da.SelectCommand.Parameters.Add(sqlparam);
                    }
                }
                da.Fill(ds);
                
            }
            
catch
            {
                ds
=null;
            }
            
finally
            {
                
this.closeDatabase();
                
            }

            
return ds;
        }

        
/// <summary>
        
/// 执行存储过程返回DataSet
        
/// </summary>
        
/// <param name="procName">存储过程名</param>
        
/// <returns></returns>
        public DataSet getDataSetExecProc(string procName)
        {
            
return getDataSetExecProc(procName, null);
        }
        
#endregion
    }

3,BLL层
代码:

 public class BLL
    {
        
public BLL()
        {

        }

        
#region 得到省份信息
        
/// <summary>
        
/// 得到省份信息
        
/// </summary>
        
/// <returns></returns>
        public DataSet GetProvince()
        {
            DAL.SQLHelper sqlhelper 
= new DAL.SQLHelper();
            DataSet ds 
= new DataSet();
            ds 
= sqlhelper.getDataSetExecProc("proc_getProvince");
            
return ds;
        }
        
#endregion

        
#region 得到城市信息
        
/// <summary>
        
/// 得到城市信息
        
/// </summary>
        
/// <param name="provinceID"></param>
        
/// <returns></returns>
        public DataSet GetCity(string provinceID)
        {
            DAL.SQLHelper sqlhelper 
= new DAL.SQLHelper();
            DataSet ds 
= new DataSet();
            SqlParameter[] param 
=new SqlParameter("@provinceid", SqlDbType.VarChar, 20) };
            param[
0].Value = provinceID;
            ds 
= sqlhelper.getDataSetExecProc("proc_getCity", param);
            
return ds;
        }
        
#endregion

        
#region 得到区县信息
        
/// <summary>
        
/// 得到区县信息
        
/// </summary>
        
/// <param name="cityID"></param>
        
/// <returns></returns>
        public DataSet GetArea(string cityID)
        {
            DAL.SQLHelper sqlhelper 
= new DAL.SQLHelper();
            DataSet ds 
= new DataSet();
            SqlParameter[] param 
=new SqlParameter("@cityid", SqlDbType.VarChar, 20) };
            param[
0].Value = cityID;
            ds 
= sqlhelper.getDataSetExecProc("proc_getArea", param);
            
return ds;
        }
        
#endregion
    }

4,前台,拖入三个dropdownlist和三个CascadingDropDown.
代码:

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

        
<asp:DropDownList ID="DropDownList1" runat="server">
        
</asp:DropDownList>
        
<asp:DropDownList ID="DropDownList2" runat="server">
        
</asp:DropDownList>
        
<asp:DropDownList ID="DropDownList3" runat="server">
        
</asp:DropDownList>
        
        
<cc1:CascadingDropDown ID="CascadingDropDown1" runat="server" Category="Province" LoadingText="正在加载省" ParentControlID="" PromptText="选择省" 
            ServiceMethod
="GetProvince" ServicePath="CityService.asmx" TargetControlID="DropDownList1" >
        
</cc1:CascadingDropDown>            
        
<cc1:CascadingDropDown ID="CascadingDropDown2" runat="server" Category="City" LoadingText="正在加载市." ParentControlID="DropDownList1" PromptText="选择市"
            ServiceMethod
="GetCity" ServicePath="CityService.asmx" TargetControlID="DropDownList2" >
        
</cc1:CascadingDropDown>
        
<cc1:CascadingDropDown ID="CascadingDropDown3" runat="server" Category="Area" LoadingText="正在加载区县." ParentControlID="DropDownList2" PromptText="选择区县"
            ServiceMethod
="GetArea" ServicePath="CityService.asmx" TargetControlID="DropDownList3" >
        
</cc1:CascadingDropDown>

 说明(转自:http://blog.csdn.net/chen_cxb/archive/2008/03/05/2148565.aspx):

1)CascadingDropDown控件的重要属性:

TargetControlID : 指定要扩展的DropDownList的ID
Category : DropDownList表示的类别名称,在WebMethod中会用到
PromptText : 没有选择时显示的文字
LoadingText : 加载数据时显示的文字
ServicePath : 获取数据的Web Service,为每个DropDownList都要指定
ServiceMethod : 获取数据的Web Method
ParentControlID : 要扩展的DropDownList的父控件ID
SelectedValue : 默认的选择项的值

刚才,我们添加的[webMethod]是GetProvince,它作为CascadingDropDown控件cascadingDropDown1的获取数据的方法 (cascadingDropDownCountry中的ServiceMethod="GetProvince"来定义这个属性),而将它关联的是DropDownList 中 DropDownList1控件(cascadingDropDown1中的TargetControlID="DropDownList1"来定义)。而另外两个City和Area控件所关联的cascadingDropDown2和 cascadingDropDown3控件呢?他们的[ServiceMethod]方法又是什么呢?我们可以看到在这两个CascadingDropDown控件的后面有一个ServiceMethod=""的属性,这个就是配置了他们的获取数据的方法。又上面的配置信息,我们可以得到他们的方法分别是GetCity和GetArea方法,这个需要我们在.cs中重新定义,类似于我们操作第一个一样。

不同的是,由于我们的第一个没有其关联的父选项DropDownList,所以,在获取数据的时候,直接就可以利用sql句获取我们想得到的数据,但是,第二个和第三个却都拥有父选项,换句话说,他们的内容是受到他们的父选项控制的,比如,我们只有在第一个DropDownList中选择了省份,我们的才能在第二个DropDownList中,动态的加载这个省份的所有城市,我们也只有选择了第二个DropDownList中的城市,我们才能在第三个DropDownList中动态添加该城市的所有区县。他们是具有父子之间的依赖关系的。

那么,他们之间是怎么联系的呢?答案就在代码中。

请注意,前台CascadingDropDown控件代码中的这个配置

           ParentControlID="Province"

      Category="city"

这两个配置的意思就是,ParentControlID定义了CascadingDropDown控件所绑定的DropDownList的控件的父选项是是什么。

而Category表示的是,它所处的类别,是用户自定义的,方便在多个CascadingDropDown控件调用一个[webMethod]的时候,实现重载。

当我们的子下拉控件绑定到父下拉的时候,根据这个控件的特色,就会产生如下的联系:

1.当父下拉控件不被选择的时候,子下拉控件是呈灰色不可操作的

2.当父下拉空间被选择的时候,子下拉空间就在其被选择后,根据父控件被选择的内容,自动加载预定信息

     他们之间的联系,就是通过ParentControlID设定后,在子控件获取数据的方法体中knownCategoryValues获得。

        [System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]

    public static CascadingDropDownNameValue[] GetCountries(string knownCategoryValues, string category)

knownCategoryValues的传递是以字符串的形式传递的,它的主要形式如下:

"provincename:000;”

"provincename:000;”Provinces:000010;"

传递一次,它就将会随之自动的增加一次。Provincename是我们下拉框选项的显示内容(text),000是下拉框在这个显示内容下的值(value).

他们是从哪里来的呢,是从我们的父下拉控件中传递过来的,如

           values.Add(new CascadingDropDownNameValue("北京", "000"));

这里面name就是“北京”,value就是“000”。

既然如此,我们就可以按照如下方式进行操作,获取父控件传递的信息,如下

方法一:截取字符串到字符串数组

 string[] categoryValues = knownCategoryValues.Split(':', ';');

方法二:利用数据字典

 StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

这两种方法是殊途同归。


新建webservice,页面名称CityService.asmx,有三个[WebMethod],分别是:GetProvince,GetCity,GetArea
完整代码:

using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Collections.Generic;//添加泛型
using AjaxControlToolkit;//
using System.Collections.Specialized;//StringDictionary

namespace myAJAX090606
{
    
/// <summary>
    
/// CityService 的摘要说明
    
/// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo 
= WsiProfiles.BasicProfile1_1)]
    [System.Web.Script.Services.ScriptService] 
//注意添加此属性,否则会报错

    
public class CityService : System.Web.Services.WebService
    {
        
#region 得到省份信息
        
/// <summary>
        
/// 得到省份信息 请参考微软的文档:http://www.asp.net/AJAX/AjaxControlToolkit/Samples/Walkthrough/CCDWithDB.aspx
        
/// </summary>
        
/// <returns></returns>
        [WebMethod]
        
public CascadingDropDownNameValue[] GetProvince()
        {
            DataSet ds 
=new DataSet();
            BLL.BLL newBLL 
= new BLL.BLL();
            ds 
= newBLL.GetProvince();
            List
<CascadingDropDownNameValue> values=new List<CascadingDropDownNameValue>();
            
if (ds.Tables.Count > 0)
            {
                
foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    values.Add(
new CascadingDropDownNameValue(dr["province"].ToString().Trim(),dr["provinceid"].ToString().Trim()));
                }
            }
            
return values.ToArray();
        }
        
#endregion

        
#region 得到城市信息
        
/// <summary>
        
/// 得到城市信息
        
/// </summary>
        
/// <param name="knownCategoryValues">得到当前选择的字符串信息包含name/value</param>
        
/// <param name="category"></param>
        
/// <returns></returns>
        [WebMethod]
        
public CascadingDropDownNameValue[] GetCity(string knownCategoryValues, string category)
        {

            StringDictionary kv 
=CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

            
string provinceID;
            
if (!kv.ContainsKey("Province"))
            {
                
return null;
            }
            
else
            {
                provinceID 
= kv["Province"].ToString();
            }

            DataSet ds 
= new DataSet();
            BLL.BLL newBLL 
= new BLL.BLL();
            ds 
= newBLL.GetCity(provinceID);
            List
<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();
            
if (ds.Tables.Count > 0)
            {
                
foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    values.Add(
new CascadingDropDownNameValue(dr["city"].ToString().Trim(), dr["cityid"].ToString().Trim()));
                }
            }
            
return values.ToArray();
        }
        
#endregion

        
#region 得到区县信息
        
/// <summary>
        
/// 得到区县信息
        
/// </summary>
        
/// <param name="knownCategoryValues"></param>
        
/// <param name="category"></param>
        
/// <returns></returns>
        [WebMethod]
        
public CascadingDropDownNameValue[] GetArea(string knownCategoryValues, string category)
        {
            StringDictionary kv 
= CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

            
string provinceID;
            
if (!kv.ContainsKey("City"))
            {
                
return null;
            }
            
else
            {
                provinceID 
= kv["city"].ToString();
            }

            DataSet ds 
= new DataSet();
            BLL.BLL newBLL 
= new BLL.BLL();
            ds 
= newBLL.GetArea(provinceID);
            List
<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();
            
if (ds.Tables.Count > 0)
            {
                
foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    values.Add(
new CascadingDropDownNameValue(dr["area"].ToString().Trim(), dr["areaid"].ToString().Trim()));
                }
            }
            
return values.ToArray();
        }
        
#endregion
    }
}

 注意:webservice一定要加上System.Web.Script.Services.ScriptService 属性。不然会报错。


三,实现效果:

最后附上ParseKnownCategoryValuesString方法的源代码:

        public static StringDictionary ParseKnownCategoryValuesString(string knownCategoryValues)
        {
            
// Validate parameters
            if (null == knownCategoryValues)
            {
                
throw new ArgumentNullException("knownCategoryValues");
            }

            StringDictionary dictionary 
= new StringDictionary();
            
if (null != knownCategoryValues)
            {
                
// Split into category/value pairs
                foreach (string knownCategoryValue in knownCategoryValues.Split(';'))
                {
                    
// Split into category and value
                    string[] knownCategoryValuePair = knownCategoryValue.Split(':');
                    
if (2 == knownCategoryValuePair.Length)
                    {
                        
// Add the pair to the dictionary
                        dictionary.Add(knownCategoryValuePair[0].ToLowerInvariant(), knownCategoryValuePair[1]);
                    }
                }
            }
            
return dictionary;
        }
原文地址:https://www.cnblogs.com/conan304/p/1497672.html