这篇文章肯定有不足的地方,希望大家指正。谢谢
另外平台是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),然后附加。
下载地址:http://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;
}