(转)回发与事件

回发与事件

基于WEB的分布式系统中,用户往往是通过提交表单,浏览器产生相应的HTTP POST请求来提出交互申请,这个过程称为回发(PostBack)。在同一个网页中,常会有许多HTML标签可能引起回发,申请交于服务器处理。
11-1A.gif
 控件对应着客户端的HTML标签,有着自己的状态和行为。用户操作引起每一次回发,会调用页面中一个或多个控件行为修改其状态,也就是说,杯中的粉圆 (《随想十》中对控件的比喻)之间是有关联的,用户拨动其中一个,可能引起其它粉圆震动。拓展开来,当用户操作或系统内部引发状态改变时,类需要发送一个消息给关联类,让关联类做相应的状态调整。在.NET框架中,这个消息被称为事件(event),发接消息的类被称为事件源(event source),关联类被称为事件接收者(event sink)。回发的处理过程,实质上是事件源调用事件接收者的行为函数,称为回调(callback)。

    我们不希望在编译时就确定回调的对象,否则这种强耦合关系就意味着每次使用时需要拎一串关联粉圆放到杯子中。相反,我们希望到运行时再来确定回调关系,在.NET框架中,这种方式被定义成委托(delegate),事件基于发布-订阅机制,每一个产生事件的类都有一个委托成员(发布机制),在系统初始化时,接收器或其它类需要将具体的事件处理程序绑定到委托成员(订阅机制),运行时,系统自动完成回调。

用户操作引发的服务器端事件
用户会对客户端浏览器中的页面元素做出各种操作,浏览器可以通过JavaScript之类的脚本语言来捕获这些操作并且做出相应回应,但对服务器而言,它却常常视而不见。要产生服务器端事件,就必须在设计期让事件源对应的表单元素引发带有鲜明特征的回发,从而让页面能够正确识别,并传递给控件以做相应回调,完成用户操作到事件的映射过程。

    ASP.NET用接口 IPostBackEventHandler做为信客的口信,带回远方的消息,它包含一个方法: RaisePostBackEvent。在回传后,页面会在控件树中寻找与引发回传HTML元素的UniqueID相匹配的控件,并调用该方法,下例为依赖于用户点击引发事件的自定义控件范例
None.gif //  MyControls.cs 自定义控件集< /font>
None.gif
using  System;
None.gif
using  System.ComponentModel;
None.gif
using  System.Web.UI;
None.gif
using  System.Web.UI.WebControls;
None.gif
None.gif
namespace  essay
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
public class myButton:WebControl,IPostBackEventHandler
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//定义控件属性Text
InBlock.gif
        public virtual string Text    
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
string s =(string)ViewState["Text"];
InBlock.gif                
return (s==null)?string.Empty:s;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ViewState["Text"]=value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif        
//生成控件对应的HTML代码
InBlock.gif
        protected override void Render(HtmlTextWriter writer) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{ writer.Write("<INPUT TYPE=submit name=" + this.UniqueID + " Value='"+this.Text+"' />"); 
ExpandedSubBlockEnd.gif        }
  
InBlock.gif        
//定义Click事件委托
InBlock.gif
        public event EventHandler Click;
InBlock.gif        
//把客户端提交映射到自定义的Click事件 
InBlock.gif
        void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    OnClick(EventArgs.Empty);    }
InBlock.gif        
//实现回调
InBlock.gif
        protected virtual void OnClick(EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{    if(Click!=null)Click(this,e);    }
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

回发数据引发的服务器端事件

    除了依赖于用户操作引发事件外,我们时常还需要根据回发的用户数据,来修改相应控件的状态,从而引发事件。

    回发的客户端表单数据会被集中整理到包含数据名/值集的一个 System.Collections.Specialized.NameValueCollection实例中,页面会利用UniqueID在控件树中寻找匹配控件,如果匹配控件实现接口 IpostBackDataHandler,则调用 LoadPostData方法更新状态并返回更新标识, RaisePostDataChangedEvent方法检查标识从而引发事件。下例为依赖于状态变化引发事件的自定义控件范例。拓展一下,可以更加灵活地使用这个事件机制,例如当用户输入特定数据时,也可以在此引发特定事件。
None.gif using  System;
None.gif
using  System.Web;
None.gif
using  System.Web.UI;
None.gif
using  System.Collections.Specialized;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
namespace  essay  dot.gif {
InBlock.gif    
public class MyTextBox: Control, IPostBackDataHandler 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif         
//定义控件属性Text
InBlock.gif
        public String Text 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gif{return (String) ViewState["Text"];}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{ViewState["Text"= value;}                  
ExpandedSubBlockEnd.gif        }
            
InBlock.gif        
//生成控件对应的HTML代码
InBlock.gif
        protected override void Render(HtmlTextWriter output) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{ writer.Write("<INPUT TYPE=text name=" + this.UniqueID + " Value='"+this.Text+"' />"); 
ExpandedSubBlockEnd.gif        }

InBlock.gif        
//定义TextChanged事件委托< span style="color: #008000;">
InBlock.gif
        public event EventHandler TextChanged;
InBlock.gif        
//更新控件的Text状态并返回更新标识
InBlock.gif
< /span>        //参数NameValueCollection为回发数据集< /span>
InBlock.gif
        public virtual bool LoadPostData(string postDataKey, 
InBlock.gif                  NameValueCollection values) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string presentValue = Text;
InBlock.gif            
string postedValue = values[postDataKey];
InBlock.gif            
if (!presentValue.Equals(postedValue))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Text 
= postedValue;
InBlock.gif                
return true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return false;
ExpandedSubBlockEnd.gif        }
    
InBlock.gif        
//检查更新标识引发自定义事件TextChanged< /span>
InBlock.gif
        public virtual void RaisePostDataChangedEvent() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{OnTextChanged(EventArgs.Empty);}
InBlock.gif        
//实现回调
InBlock.gif
        protected virtual void OnTextChanged(EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{if (TextChanged != null)TextChanged(this,e);}         
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
    
None.gif


非回发事件与完整的控件执行生命周期
以上两个事件机制皆与回发有直接关系,利用.NET的事件框架,我们可以在控件中的任何一个地方引发非回发事件。例如我们可以在页面中加入对用户透明的用户行为分析处理控件,窥视其它控件状态从而引发其特定的事件。

     至此,我们已经深入了解与控件执行相关的各种要素细节,最后,通过图11-2,我们小结一下控件完整的执行生命周期

11-2A.gif
http://www.cnblogs.com/hunanboy/archive/2006/11/22/568452.html

转载于:https://www.cnblogs.com/skyblue/archive/2007/07/25/831054.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值