简单三层+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,数据库的三个存储过程,分别得到省、市、区县信息。很简单。
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层。
简单的代码:
{
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 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.
代码:
<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.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方法的源代码:
{
// 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;
}