大家已經在知道在我們開發ASPNET網站的時候每個服務器控件都有自己的ID為了後面更好的展開下面我們就來簡單的看看這個場景當我們在浏覽器中點擊了一個服務器控件如 Button此時頁面回傳給服務器然後服務器就引發控件的Click等事件這個場景是簡單的不能在簡單了
我們來進一步看我們知道不是所有的控件都會在服務器端觸發事件的比如 submit按鈕這個按鈕也同樣可以把表單數據傳到服務器但是這個控件不能在服務器端觸發事件其實在一個頁面提交到了服務器之後服務器就會檢查是哪個控件引起了頁面提交然後就把這個控件的ID找到然後再在我們請求的那個頁面如Defaultaspx (假設我們點擊按鈕請求的是Defaultaspx)去找是否有服務器控件的ID和此時提交頁面的ID是一樣的如果有那麼就在頁面的生命周期的合適的時候引發事件在把處理的結果返回如果沒有服務器就不做什麼了特別的處理
還有一點要注意的是在查找那個控件的ID 的時候頁面(如Defaultaspx)已經被編譯成為了一個繼承自Page的類
當然上面說的只是一個很粗略額過程希望大家有個總體的認識下面就細致的講解
我通過一個流程來解釋
我們首先請求一個服務器端的頁面如x為了方便解釋假設頁面只有三個服務器控件TextBoxDropDowmListButton
定義如下
<%@ Page Language=C# %>
<!DOCTYPE html PUBLIC //WC//DTD XHTML Transitional//EN transitionaldtd>
<html xmlns=>
<head runat=server>
<title>Untitled Page</title>
</head>
<body>
<form id=form runat=server>
<asp:TextBox runat=server ID=TextBox />
<asp:DropDownList runat=server ID=DropDownList>
<asp:ListItem Text=Text Value=Value />
<asp:ListItem Text=Text Value=Value />
<asp:ListItem Text=Text Value=Value />
</asp:DropDownList>
<asp:Button runat=server Text=Submit />
</form>
</body>
</html>
在浏覽器中我們在源中看到的如下
<!DOCTYPE html PUBLIC //WC//DTD XHTML Transitional//EN
transitionaldtd>
<html xmlns=>
<head>
<title>Untitled Page </title>
</head>
<body>
<form name=form method=post action=Defaultaspx id=form>
<div>
<input type=hidden name=__VIEWSTATE id=__VIEWSTATE
value=/wEPDwUKMTAxNzkMjYOWRkxj+HeOcNxVutpxOdaSpw= />
</div>
<input name=TextBox type=text id=TextBox />
<select name=DropDownList id=DropDownList>
<option value=Value>Text</option>
<option value=Value>Text</option>
<option value=Value>Text</option>
</select>
<input type=submit name=ctl value=Submit />
</form>
</body>
</html>
確實上面的那些HTML的代碼確實沒有什麼但是大家注意看看TextBoxDropDownList它們的ID在服務器端的aspx頁面和本地的源中的ID是一樣的
我們在浏覽器中的TextBox中輸入xiaoyang然後DropDowList 選中Text然後我們點擊按鈕提交此時我們提交的數據被包含在表單中的而且是以這樣的格式保存的TextBox=xiaoyang&DropDownList=Value不用多說表單數據是用&來分隔的而且每個分隔的串包含兩個部分ID和值也就是鍵值對
數據到了服務器後ASPNET就實例化一個 HttpRequest的類這個類有兩個屬性 Forms和 QueryString它們的類型都是NameValueCollection(鍵值對大家可以把它看成一個HashTable)然後ASPNET解析表單數據表單數據就解析成為了一個個的鍵值對然後就保存在Forms(POST提交)或者QueryString中(GET提交)我們之前是以POST提交為例子的
之前的事情是發生在頁面的生命周期之前的當頁面調用自己的ProcessRequest方法後就進入了頁面生命周期此時頁面就會檢查頁面中的所有控件看看它們有哪些實現了IPostBackDataHandler接口然後把實現了這些接口的控件都放入到一個ArrayList中然後也檢查哪些控件實現了IPostBackEventHandler也把它們假如到另外的集合中之後就開發遍歷實現了IPostBackDataHandler控件的集合並且調用IPostBackDataHandler的方法LoadPostData(string postdatakeyNameValueCollection value)
之前說過了的我們提交的表單的值都保存在了Forms中(它的類型是NameValueCollection 的)所以此時這些值就傳入到了這個方法然後就檢查這些值和之前的是不是相同的我們已經還記得我們在浏覽器中看到頁面時頁面中的TextBox 初始時是沒有值的而且DropDownList選擇的是Text現在我們的值改了是xiaoyang和Text所以這個方法檢查的結果是值變了返回了true只要返回了true那麼IPostBackDataHandler的下一個方法就會調用RaisePostDataChangeEvent()這個方法已經注冊了事件到頁面生命周期的之後就後引發的
所以如果我們開發的自定義控件想要在數據改變的時候引發事件那麼就一定要實現IPostBackDataHandler接口例子可以參看我的另外的控件開發的系列文章
現在我們已經說到了數據的改變下面就看看到底是怎麼引發事件的到了頁面開發執行RaisePostbackEvent方法的時候頁面就會遍歷實現了IPostBackEventHandler的控件的集合並且檢查是否在頁面中存在一個控件這個控件要實現了IPostBackEventHandler並且ID和之前使得頁面提交到服務器的的那個控件的ID一樣如果有IPostBackEventHandler的RaisePostBackEvent 方法來觸發事件(不同控件實現這個方法的方式不同)如Click事件
所以如果想在自定義控件可以觸發事件那麼就要實現IPostBackEventHandler接口可以參看我的控件開發系列文章有例子的
今天到這裡!謝謝大家
From:http://tw.wingwit.com/Article/program/net/201311/12865.html