ASP.NET2.0 中回调的实现及常见问题的解决

要实现无刷新更新数据控件需要分三步走:
  1. 客户端脚本触发回调方法
  2. 服务器端代码响应回调,并更新数据控件,将更新后的数据控件内容(html编码)发回客户端
  3. 客户端代码根据发回的内容重绘该数据控件

示例代码中,空白的页面上有三个DropDownListBox控件 DropDownListBox_ADropDownListBox_BDropDownListBox_C,最终的目的是实现在页面不刷新的情况下当DropDownListBox_A的选择更改时动态的更新DropDownListBox_B和DropDownListBox_C的内容,实现联动。

在服务器端,首先要让自己的页面实现 ICallbackEventHandler接口,如:
None.gif public  partial  class  _Default : System.Web.UI.Page, ICallbackEventHandler

然后在页面上添加如下三个方法及一个公共string,固定套路:

ContractedBlock.gif ExpandedBlockStart.gif 回调三人组 #region 回调三人组
InBlock.gif
public string str_CallBack;
InBlock.gif
InBlock.gif
//引发回调事件处理
InBlock.gif
public void RaiseCallbackEvent(string the_id)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    str_CallBack 
= the_id;
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
//回传回调结果
InBlock.gif
public string GetCallbackResult()
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    
//    将前台传送来的参数分解
InBlock.gif
    string[] parts = str_CallBack.Split('|');
InBlock.gif
InBlock.gif    
//    构造参数队列
InBlock.gif
    object[] theObject = new object[parts.Length - 1];
InBlock.gif    
for (int int_index = 1; int_index < parts.Length; int_index++)
InBlock.gif        theObject[int_index 
- 1= parts[int_index];    
InBlock.gif
InBlock.gif    
//    调用Page Method
InBlock.gif
    return (string)GetType().GetMethod(parts[0]).Invoke(this, theObject);
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
private string RenderControl(Control control)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    StringWriter writer1 
= new StringWriter(CultureInfo.InvariantCulture);
InBlock.gif    HtmlTextWriter writer2 
= new HtmlTextWriter(writer1);
InBlock.gif
InBlock.gif    control.RenderControl(writer2);
InBlock.gif    writer2.Flush();
InBlock.gif    writer2.Close();
InBlock.gif
InBlock.gif    
return writer1.ToString();
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif
#endregion

然后声明一个更新数据控件的方法,比如示例中的        

 1 None.gif public   string  BindDropDownList_B( string  str_index)
 2 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 3InBlock.gif        //  简单绑定
 4InBlock.gif         DropDownList_B.Items.Clear();
 5InBlock.gif        for (int i = 0; i < 20; i++)
 6ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 7InBlock.gif            ListItem newItem = new ListItem();
 8InBlock.gif            newItem.Text = string.Format("{0} - B{1}", str_index, i.ToString());
 9InBlock.gif            DropDownList_B.Items.Add(newItem);
10ExpandedSubBlockEnd.gif        }

11InBlock.gif
12InBlock.gif        return RenderControl(DropDownList_B);
13ExpandedBlockEnd.gif}

14 None.gif
15 None.gif public   string  BindDropDownList_C( string  str_index)
16 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
17InBlock.gif        DropDownList_C.Items.Clear();
18InBlock.gif        for (int i = 0; i < 30; i++)
19ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
20InBlock.gif            ListItem newItem = new ListItem();
21InBlock.gif            newItem.Text = string.Format("{0} - C{1}", str_index, i.ToString());
22InBlock.gif            DropDownList_C.Items.Add(newItem);
23ExpandedSubBlockEnd.gif        }

24InBlock.gif
25InBlock.gif        return RenderControl(DropDownList_C);
26ExpandedBlockEnd.gif}

在客户端,你需要将两个数据控件的Html编码用<span></span>包起来,id分别为span_bspan_c,并在header中声明如下脚本:

 1 None.gif < script language = " javascript "  type = " text/javascript " >
 2 None.gif //   DropDownList_A的change
 3 None.gif function  OnChanged()
 4 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 5InBlock.gif        var context = span_b;
 6InBlock.gif        var theControl = document.getElementById("DropDownList_A");
 7InBlock.gif        //  调用服务器方法BindDropDownList_B,并将A当前选择的index传过去
 8InBlock.gif         var arg = "BindDropDownList_B|" + theControl.selectedIndex;
 9InBlock.gif        
10InBlock.gif        <%= ClientScript.GetCallbackEventReference(this"arg""UpdataDropDownList_B""context")%>;
11ExpandedBlockEnd.gif}

12 None.gif    
13 None.gif function  UpdataDropDownList_B(result, context)
14 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
15InBlock.gif        //  重画控件
16InBlock.gif         context.innerHTML = result;
17InBlock.gif        //  避免同时更新失败
18InBlock.gif         setTimeout("elsefunction()"1);
19ExpandedBlockEnd.gif}

20 None.gif    
21 None.gif function  elsefunction()
22 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
23InBlock.gif        var context = span_c;
24InBlock.gif        var theControl = document.getElementById("DropDownList_A");        
25InBlock.gif        var arg = "BindDropDownList_C|" + theControl.selectedIndex;
26InBlock.gif        
27InBlock.gif        <%= ClientScript.GetCallbackEventReference(this"arg""UpdateDropDownList_C""context")%>;
28ExpandedBlockEnd.gif}

29 None.gif    
30 None.gif function  UpdateDropDownList_C(result, context)
31 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
32InBlock.gif        context.innerHTML = result;    
33ExpandedBlockEnd.gif}

34 None.gif </ script >

最后在Page_Load中为DropDownList_A添加onchange属性

None.gif DropDownList_A.Attributes.Add( " onchange " " OnChanged() " );

直接点运行吧,注意看IE的进度条。是不是无刷新实现了下拉列表的联动:)

    需要说明的是,如果在Javascript脚本的OnChanged中接连两次回调服务器方法的话只有最后一次奏效,并且会有JavaScript报错,原因是微软的客户端回调实现代码中有一个缺陷:无论客户端回调了多少次,只要有一次回调完成,则视所有回调均完成,不是线程安全的!所以上述代码中使用了setTimeout做了中转,具体原因详见http://developers.de/files/279/download.aspx.
    
    以上代码虽很好的完成了无刷新前提下的数据控件更新,但仍有一个问题至今没有解决,就是虽然控件的数据重新更新了,但是状态却还是最后一次PostBack时的状态(本例中为初始状态),如果你去取某个下拉框的值,仍就是初始值,不知道哪位朋友有这方面的解决办法,万分感谢!

转载于:https://www.cnblogs.com/lianyonglove/archive/2007/04/04/699959.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值