用回调实现的省市县区四级下拉选择联动的例子

本文示例代码(52K),请在VS2005中用"打开网站"的方式打开并运行

上个月贴过一个用回调实现的下拉列表联动的例子,不过那个示例相对简单,只阐述了概念,离实际的运用还有距离,今天再贴一个用回调实现的地区选择的例子,不附加任何第三方DLL,数据库也用最基本的Access构成,可以方便的转换成其它数据库,喜欢的朋友可以方便的转为己用。

闲话少说,先看下回调的关键部分,Javascript部分是发起回调,并接收返回的结果

function OnProvinceChanged()
{
    
    
//  控制一个ID为td_cities的<td>内部控件的更新
    var context = document.getElementById("td_cities");
    
var theDDL_Province = document.getElementById("DropDownList_Provinces");        
    
//  调用服务器方法UpdateCities,并将DropDownList_Provinces当前选择的value传过去
     var arg = "UpdateCities|" + theDDL_Province.value;
        
    
<%= ClientScript.GetCallbackEventReference(this"arg""UpdataDropDownList_Cities""context"%>;
}


//  接收回调后服务器传回的结果,这里是DropDownList_Provinces控件重新绑定后的HTML编码
function UpdataDropDownList_Cities(result, context)
{
    
//  控件的前台"更新"
    context.innerHTML = result;    
}
在Javascript中调用服务器端方法可能不止一个参数,此时arg的构成格式为:"服务器方法名" + "|" + "参数1" + "|" + "参数2" + ... 需要说明的是,这里的服务器方法必须是public的,接收的参数均为string类型,否则会出错。再看下服务器端三个核心的方法:
#region 回调实现,固定的写法
public string str_content;

//  接收Javascript传过来的arg为the_string
public void RaiseCallbackEvent(string the_string)
{
    str_content 
= the_string;
}


//  根据arg构造参数序列并调用服务器端方法
public string GetCallbackResult()
{
    
//  拆分由客户端传过来的参数
    string[] parts = str_content.Split('|');

    
//  生成ServerMethod的参数队列
    object[] theArgList = new object[parts.Length - 1];
    
for (int int_index = 1; int_index < parts.Length; int_index++)
        theArgList[int_index 
- 1= parts[int_index];

    
//  调用ServerMethod
    return (string)GetType().GetMethod(parts[0]).Invoke(this, theArgList);
}


//  返回指定控件的HTML编码
private string RenderControl(Control control)
{
    StringWriter writer1 
= new StringWriter(CultureInfo.InvariantCulture);
    HtmlTextWriter writer2 
= new HtmlTextWriter(writer1);

    control.RenderControl(writer2);
    writer2.Flush();
    writer2.Close();

    
return writer1.ToString();
}

#endregion
其中前两个方法可以在实现ICallbackEventHandler接口时由代码提示辅助生成,ICallbackEventHandler的namespace为System.Web.UI.ICallbackEventHandler,为了使用方法RenderControl中的StringWriter及CultureInfo还必须在文件头添加对他们的引用
using System.Web.UI;
using System.IO;
using System.Globalization;
服务器端对下拉控件的更新如下,相对正常的绑定只做了很小的更改
//  更新地级市
public string UpdateCities(string str_ProvinceID)
{
    
return UpdateDropDownList(str_ProvinceID, DropDownList_Cities);
}


//  根据上级编号更新指定的DropDownList
private string UpdateDropDownList(string str_parent_id, DropDownList theDropDownList)
{
    
string str_SQL = "Select area_id, area_name From Cities Where area_parent_id = '" + str_parent_id + "' Order By area_id Asc";

    DataTable theDataTable 
= GetDataTable(str_SQL);

    
if (theDataTable == null)
        
return string.Empty;

    
//  数据绑定
    theDropDownList.DataSource = theDataTable;
    theDropDownList.DataTextField 
= "area_name";
    theDropDownList.DataValueField 
= "area_id";
    theDropDownList.DataBind();

    
//  返回的是Javascript便于处理的string
    if (str_parent_id == "000000")
        
//  省级列表不需要联动
        return string.Empty;
    
else
        
return RenderControl(theDropDownList);
}

4个下拉列表的联动需要涉及到3次回调过程,限于微软在回调JS端的代码BUG,这3次回调只能用串联进行,中间用setTimeout()连接,否则会有Javascript报错,这也算是回调的一大缺陷吧。
Access中表Ctities的组织如下,area_parent_id顾名思义是该地区上级地区的编码,省级的上级是000000,这里我收集了3523条记录,基本涵盖了大江南北

更细节的地方还是在示例代码中找答案吧。

回调说到底还是微软对xmlhttp对象操作的封装,和其它Ajax实现大同小异,微软制定了固定的流程套路来降低Ajax的开发门槛,不用额外第三方DLL的支持是其最大的亮点,因此可以稳定在各支持ASP2.0的Server上运行,当然,回调并不是ASP2.0独有的,在ASP1.1时就已存在。

posted @ 2006-08-17 15:01  翅膀  阅读(508)  评论(0编辑  收藏  举报