记得以前做asp的时候,常会碰到下拉框多级联动,比如说在注册的时候,需要选择省和城市,这就需要二级联动,那个时候一个普遍的做法就是利用 javascript脚本来实现,先把数据从数据库中读取出来,放到javascript的数组中,在下拉框的onchange事件触发时,就可以直接从 javascript的数组中读取想要的数据。后来在asp.net 1.0中开发时,这种方法也通用,但如果要多级的话,有一个很大的缺点,就是它需要把数据一次性全部读到javascript的数组中,如果数据非常庞大 的话,这部分开销是很大的,有时候不把数据放到数据中中,而是直接写在javascript中,这样不易于维护,而且代码也太长,如果要开发可以无限级联 的话,那更是比较头痛。自从asp,net 2.0问世后,开始学习新技术,发现asp,net2.0不仅在控件上,功能上都产生了大变化,而且在对javascript客户脚本的调用功能也更加强 大了,特别是出现了ajax功能,即客户端回调功能(当然这只是一个小小的ajax功能,如果要实现功能更强大的无刷新可看atlas),利用这个特性可 以很方便的开发现无限级联动的下拉框效果。
1、先在数据库里建立相应的数据表如下:
2、建立读取数据表的函数,这里就不写出来了,我想每个人都会有不同的方法去实现这一功能。
3、接下来,我们就可以进行页面设置了,我们先做一个二级联动的效果,在页面上放置二个下拉框控件,上面一个为TestDropDownList,下面一 个为Item1,再加入一个objectdatasource控件,用来读取parentId为0的所有记录绑定到TestDropDownList下拉 框中,如下图:
如果要使用客户端回调,必须要实现System.Web.UI.ICallbackEventHandler接口。
1public partial class Test : System.Web.UI.Page , System.Web.UI.ICallbackEventHandler
2{
该接口下面,有二个方法:
a)、void System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent(string eventArguent)
该方法接收客户端传过来的参数enentArguent,这个参数好象只能是string型,并且没有返回值,我们可以根据传过来的参数,来执行相应的 功能,在这里我们不能对页面进行重新绑定等操作,但能够跟数据库进行交互操作,如读取、删除、插入等操作,在本文的例子中,这里从客户端传过来的是 parentId的值,再从数据库中读取parentId为相应值的所有记录,具体代码如下:
1void System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent(string eventArguent)
2 {
3 DataSet ds = new GetData().TestByParentId(Convert.ToInt32(eventArguent));
4 foreach(DataRow row in ds.Tables[0].Rows)
5 {
6 if (result.Equals(string.Empty))
7 {
8 result = row["pkId"] + "@" + row["name"].ToString();
9 }
10 else
11 {
12 result = result + "," + row["pkId"] + "@" + row["name"].ToString();
13 }
14 }
15 }
在这里,通过TestByParentId(Convert.ToInt32(enentArguent))函数读到相应数据,并把得到的数据作了一些处理,这个为什么要这样做,请继续往下看。这里的result为string型变量。
b)、string System.Web.UI.ICallbackEventHandler.GetCallbackResult()
这是第二个方法,该方法没有参数,返回只能返回string型。这个方法是用来数据回调的,上面那个方法接收客户端传过来的参数,进行处理后,还要把处 理后的我们想要的数据传回到客户端去执行,才会有用。这里我们也看到了,由于该方法只能返回string型,而在下拉框必须有二个值,一个是 DataValue,另一个是DataText,所以在上面的方法中,通过@符号,把这二个值合在一起,便于在客户端程序中进行分离。这个方法功能很简 单,就是把result返回即可,如下:
1string System.Web.UI.ICallbackEventHandler.GetCallbackResult()
2 {
3 return result;
4 }
现在我们实现了System.Web.UI.ICallbackEventHandler接口下的全部方法,接下来我们就可以来写客户端的程序了,用 javascript来实现。这里主要也有二个方法,第一个方法用来接受下拉框控件的onchange事件触发响应,另一个用来接收string System.Web.UI.ICallbackEventHandler.GetCallbackResult()方法传递过来的result值,并做 相应处理,把数据绑定到第二个下拉框中去,实现 二级联动。主要代码如下
a)、第一个方法
1 function CallServer(input, context)
2 {
3 context.length=0;
4 context.options[context.length]=new Option("数据读取中","0");
5
6 arg = input.value;
7 <%=callback %>
8 }
这里有二个参数,input是用来触发onchange的下拉框控件名称,context是要级联的下拉框名称,这里在数据还没有绑定之前,级联下拉框 显示“数据读取中...”字样。arg接收input下拉框的值,这个值以后是传递到上面的eventArguent参数中去,其中的<%= callback%>我们下面再介绍。
b)、第二个方法
1 function ReceiveServerData(result, context)
2 {
3 context.length=0;
4 var arrData = result.split(",");
5 for (var i = 0; i < arrData.length; i++)
6 {
7 var data = arrData[i].split("@");
8 context.options[context.length]=new Option(data[1],data[0]);
9 }
10
11 }
这里也有二个参数,其中result,就是接收上面讲到的result值,而context同第一个方法的context。这里通过js的split方法,把数据进行处理,再绑定到context控件中去,通过这个就可以在第二个下拉框中出现相应的值了。
做到这里基本上已经大功告成了,不过还有最后一步,这也是最重要的一步,我们现在做的只是客户端归客户端,服务器方法归服务器方法,那么怎么样把这二个 联系起来呢,这也是实现客户端回调的关键部分,这里需要使用Page.ClientScript.GetCallbackEventReference方 法,下面是摘自MSDN2上的对ClientScript.GetCallbackEventReference(……)的详细说明。
public string GetCallbackEventReference (Control control,string argument,string clientCallback,string context)
参数:
参数 作用
control 处理客户端回调的服务器 Control。该控件必须实现 ICallbackEventHandler 接口并提供 RaiseCallbackEvent 方法。
argument 从客户端脚本传递一个参数到服务器端的RaiseCallbackEvent 方法。
clientCallback 一个客户端事件处理程序的名称,该处理程序接收服务器端事件返回的结果。
context 启动回调之前在客户端的客户端脚本信息。脚本的结果传回给客户端事件处理程序。
返回值 调用客户端回调的客户端函数的名称。
下面是ClientScriptManager.GetCallbackEventReference 方法的重载列表
名称 说明
ClientScriptManager.GetCallbackEventReference (Control, String, String, String) 获取一个对客户端函数的引用;调用该函数时,将启动一个对服务器端事件的客户端回调。此重载方法的客户端函数包含指定的控件、参数、客户端脚本和上下文。
ClientScriptManager.GetCallbackEventReference (Control, String, String, String, Boolean) 获取一个对客户端函数的引用;调用该函数时,将启动一个对服务器端事件的客户端回调。此重载方法的客户端函数包含指定的控件、参数、客户端脚本、上下文和 布尔值。
ClientScriptManager.GetCallbackEventReference (Control, String, String, String, String, Boolean) 获取一个对客户端函数的引用;调用该函数时,将启动一个对服务器端事件的客户端回调。此重载方法的客户端函数包含指定的控件、参数、客户端脚本、上下文、 错误处理程序和布尔值。
ClientScriptManager.GetCallbackEventReference (String, String, String, String, String, Boolean) 获取一个对客户端函数的引用;调用该函数时,将启动一个对服务器端事件的客户端回调。此重载方法的客户端函数包含指定的目标、参数、客户端脚本、上下文、 错误处理程序和布尔值。
主要实现如下:
在page_load里加入下面语句
1callback = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context");
其中,arg就是用来从客户端传递参数,最终传到enentArguent中,ReceiveServerData是一个客户端方法,用来接收服务器端回调过来的数据。
再把callback这个字符串放在第一个客户端方法下面(请看上面的第一个客户端方法)
这个完成后,我们只要把第一个下拉框的onchange客户端事件加入就可以了,在page_load里加入
1TestDropDownList.Attributes["onchange"] = "javascript:CallServer(TestDropDownList , Item1)";
做完所有这些,程序应该能够正常动行了
现在二级联动已经成功,那怎么能够实现多级的呢,其实大家只要仔细的看一下,就不难发现,当我触到一个下拉框的onchange事件,通过 callServer读取值,再通过<%callback%>来启动 void System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent(string eventArguent)这个方法,把数据处理后,通过string System.Web.UI.ICallbackEventHandler.GetCallbackResult()方法返回,再由 ReceiveServerData客户端来把数据绑定到相应原下拉框中,而这里的二个互动的下拉框都是通过参数来传递的, TestDropDownList.Attributes["onchange"] = "javascript:CallServer(TestDropDownList , Item1)"; 这样的话,我们可以改变这里传递的控件参数名,就可以重复利用这四个方法,也就是这样就可以实现,无限级联动。我们再加入一个下拉框, 取名Item2,我们只要在page_load中加入如下语句即可:
1Item1.Attributes["onchange"] = "javascript:CallServer(Item1 , Item2)";
就就可以三级联动了,如果要四级,五级,只要加入下应的下拉框,并在page_load中加入相应的onchange事件触发,就可以实现了
不过这种方法目前还有一个很大的二个缺点:
1、那就是当第一个选择后,第二个下拉框会出现相应的值,而第三个以及下面的几个不会变,只有再选择第二个下拉框的值后,第三个才会改变
2、由于1的问题,导致如果第二个下拉框中只有一个值,那么第三个以及以下几个都不能发生改变了,不知道大家有没有好的解决方法,我相信应该有解决的方法的。
由于本人水平有限,可能有不当之处,希望大家能够指正,谢谢!