Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1143203
  • 博文数量: 141
  • 博客积分: 3161
  • 博客等级: 中校
  • 技术积分: 3011
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-27 14:53
文章存档

2012年(28)

2011年(113)

分类: 嵌入式

2011-12-28 20:29:00

     前言:当我们把页面中的数据包含在表单中发送到服务器的时候,数据到底是以什么形式发送的?服务器接受到提交的数据后是如何读取这些数据,又是如何要决定来引发事件的?我们怎么样才能让我们自定义的控件能够在服务器端触发事件?为什么服务器控件有的要实IPostBackEventHandler,IPostBackDataHandler?.....

 

    大家已经在知道,在我们开发ASP.NET网站的时候,每个服务器控件都有自己的ID。为了后面更好的展开,下面我们就来简单的看看这个场景:当我们在浏览器中点击了一个服务器控件,如 Button,此时页面回传给服务器,然后服务器就引发控件的Click等事件,这个场景是简单的不能在简单了。

 

    我们来进一步看,我们知道,不是所有的控件都会在服务器端触发事件的,比如 submit按钮,这个按钮也同样可以把表单数据传到服务器,但是这个控件不能在服务器端触发事件。其实在一个页面提交到了服务器之后,服务器就会检查是哪个控件引起了页面提交,然后就把这个控件的ID找到,然后再在我们请求的那个页面,如Default.aspx (假设我们点击按钮,请求的是Default.aspx),去找是否有服务器控件的ID和此时提交页面的ID是一样的,如果有,那么就在页面的生命周期的合适的时候,引发事件,在把处理的结果返回;如果没有,服务器就不做什么了特别的处理。

 

     还有一点要注意的是,在查找那个控件的ID 的时候,页面(如Default.aspx),已经被编译成为了一个继承自Page的类

     当然,上面说的只是一个很粗略额过程,希望大家有个总体的认识。下面就细致的讲解。

 

     我通过一个流程来解释:

     1.我们首先请求一个服务器端的页面,如:。为了方便解释,假设页面只有三个服务器控件:TextBox,DropDowmList,Button

     定义如下:

  

  1. <%@ Page Language=”C#” %>
  2. <!DOCTYPE html PUBLIC-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
  3. <html xmlns=”http://www.w3.org/1999/xhtml”>
  4. <head runat=”server”>
  5. <title>Untitled Page</title>
  6. </head>
  7. <body>
  8. <form id=”form1” runat=”server”>
  9.      <asp:TextBox runat=”server” ID=”TextBox1” />

  10.      <asp:DropDownList runat=”server” ID=”DropDownList1”>
  11.      <asp:ListItem Text=”Text1” Value=”Value1” />
  12.      <asp:ListItem Text=”Text2” Value=”Value2” />
  13.      <asp:ListItem Text=”Text3” Value=”Value3” />
  14.      </asp:DropDownList>

  15.      <asp:Button runat=”server” Text=”Submit” />
  16. </form>
  17. </body>
  18. </html>
 

    在浏览器中,我们在”源“中,看到的如下:

 

  1. <!DOCTYPE html PUBLIC-//W3C//DTD XHTML 1.0 Transitional//EN”
  2. “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
  3. <html xmlns=”http://www.w3.org/1999/xhtml”>
  4. <head>
  5. <title>Untitled Page </title>
  6. </head>
  7. <body>
  8. <form name=”form1” method=”post” action=”Default7.aspx” id=”form2”>
  9. <div>
  10. <input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE”
  11. value=/wEPDwUKMTAxNzk2MjY2OWRkxj+0HeO0c5N0xVutp03x6OdaSpw=/>
  12. </div>
  13. <input name=”TextBox1” type=”text” id=”TextBox1” />
  14. <select name=”DropDownList1” id=”DropDownList1”>
  15. <option value=”Value1”>Text1</option>
  16. <option value=”Value2”>Text2</option>
  17. <option value=”Value3”>Text3</option>
  18. </select>
  19. <input type=”submit” name=”ctl02” value=”Submit” />
  20. </form>
  21. </body>
  22. </html>
 

     确实,上面的那些HTML的代码确实没有什么,但是大家注意看看TextBox,DropDownList,它们的ID在服务器端的aspx页面和本地的源中的ID是一样的。

 

     2.我们在浏览器中的TextBox中输入"xiaoyang",然后DropDowList 选中"Text2",然后我们点击按钮,提交。此时我们提交的数据被包含在表单中的,而且是以这样的格式保存的"TextBox1=xiaoyang&DropDownList1=Value2",不用多说,表单数据是用"&"来分隔的,而且每个分隔的串包含两个部分:ID和值,也就是"键值对"。

 

     3.数据到了服务器后,ASP.NET就实例化一个 HttpRequest的类,这个类有两个属性 Forms和 QueryString,它们的类型都是NameValueCollection(键值对,大家可以把它看成一个HashTable),然后ASP.NET解析表单数据,表单数据就解析成为了一个个的键值对,然后就保存在Forms(POST提交)或者QueryString中(GET提交)。我们之前是以POST提交为例子的。

 

     4.之前的事情是发生在页面的生命周期之前的。当页面调用自己的ProcessRequest方法后,就进入了页面生命周期,此时页面就会检查页面中的所有控件,看看它们有哪些实现了IPostBackDataHandler接口,然后把实现了这些接口的控件都放入到一个ArrayList中,然后也检查哪些控件实现了IPostBackEventHandler,也把它们假如到另外的集合中,之后就开发遍历实现了IPostBackDataHandler控件的集合,并且调用IPostBackDataHandler的方法:LoadPostData(string postdatakey,NameValueCollection value)。

 

     之前说过了的,我们提交的表单的值都保存在了Forms中(它的类型是NameValueCollection 的),所以此时这些值就传入到了这个方法,然后就检查这些值和之前的是不是相同的,我们已经还记得,我们在浏览器中看到页面时,页面中的TextBox 初始时是没有值的,而且DropDownList选择的是Text2,现在我们的值改了,是“xiaoyang"和"Text2".所以这个方法检查的结果是:值变了,返回了true.只要返回了true,那么IPostBackDataHandler的下一个方法就会调用RaisePostDataChangeEvent();这个方法已经注册了事件,到页面生命周期的之后就后引发的。

 

     5.所以,如果我们开发的自定义控件想要在数据改变的时候引发事件,那么就一定要实现IPostBackDataHandler接口。例子可以参看我的另外的控件开发的系列文章。

 

     6.现在我们已经说到了数据的改变。下面就看看到底是怎么引发事件的。到了页面开发执行RaisePostbackEvent方法的时候,页面就会遍历实现了IPostBackEventHandler的控件的集合,并且检查是否在页面中存在一个控件:这个控件要实现了IPostBackEventHandler,并且ID和之前使得页面提交到服务器的的那个控件的ID一样。如果有IPostBackEventHandler的RaisePostBackEvent 方法来触发事件(不同控件实现这个方法的方式不同),如Click事件。

     所以,如果想在自定义控件可以触发事件,那么就要实现IPostBackEventHandler接口。可以参看我的控件开发系列文章,有例子的。

 

     今天到这里!谢谢大家。

阅读(1075) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~