__doPostBack方法解析 __VIEWSTATE __EVENTTARGET __doPostBack __EVENTARGUMENT
關於這個的另一篇博客:http://www.cnblogs.com/Silicon-Fado/archive/2009/04/21/1440437.html
__VIEWSTATE:頁面狀態信息在客戶端的存儲(ViewState中存儲的信息, EnableViewState="true"的控件狀態信息).
__EVENTTARGET:頁面回傳觸發事件 頁面回傳觸發事件:
__doPostBack(‘Button2‘,‘‘)表示調用按鈕Button2在後端的所對應的單擊事件 控件回傳觸發事件:
__doPostBack(‘TEST1$Button1‘,‘‘)表示調用TEST1控件中的Button1按鈕的Click方法
__EVENTARGUMENT:頁面回傳觸發事件時所帶的參數 如:__doPostBack(‘Button1‘,‘aa‘)在後端可以使用Request.Form["__EVENTARGUMENT"]來取得
.net自動生成的一些客戶端的代碼 用來回傳數據和自己帶的一些腳本函數
=====================================================================
今天工作時遇到一個需要根據Gridview具體內容來判斷是否彈出窗口,而Gridview中包含分頁、排序等,它們並不能直接從查詢字符串、或表單簡單的分析出。這是因為存在__doPostBack方法,以及和其緊密關聯的__ EVENTTARGET和__ EVENTARGUMENT。
function __doPostBack(eventTarget, eventArgument)的eventTarget參數是GridView控件的名字,eventArgument參數是命令字。當如果是刪除時,eventArgument參數是Delete開頭;當如果是插入時,eventArgument參數是Insert開頭;當如果是編輯時,eventArgument參數是Edit開頭;當如果是選擇時,eventArgument參數是Select開頭。
============================================================
客戶端觸發事件後調用__doPostBack方法,將表示觸發的控件源的eventTarget 和事件參數eventArgument分別付給兩個隱藏域__EVENTTARGET和__EVENTARGUMENT,然後提交Form,在服務端根據 __EVENTTARGET和__EVENTARGUMENT來判斷是哪個控件的什麽事件觸發了。
< script language= "javascript" >
function __doPostBack(eventTarget, eventArgument)
{
var theform = document.WebForm2;
theform.__EVENTTARGET.value = eventTarget;
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
< /script>
|
=================================================================Asp.net的postback機制我們知道Asp.net輸出到客戶端時都會被轉化為HTML,頁面Render到Client後,Client的HTML代碼將包含如下代碼:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTA0NDQ2OTE5OWRk281L4eAk7iZT10hzg+BeOyoUWBQ=" />
<script type="text/javascript">
<!-- var theForm = document.forms[‘form1‘]; if (!theForm)
{
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument)
{
if (!theForm.onsubmit || (theForm.onsubmit() != false))
{
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;theForm.submit();
}
} // -->
</script>
其中隱藏字段_EVENTTARGET代表觸發事件的控件。_EVENTARGUMENT代表事件的額外參數。為了頁面能在PostBack後依然能讀取服務器控件原有的狀態數據,Asp.net中使用了ViewState技術,而ViewState技術本質上是用一個默認名稱為__VIEWSTATE的Hidden類型表單域來保存和傳遞數據(這些數據是經過了序列化後Base64編碼的字符串值)。控件的事件被Render後事件變成javascript:__doPostBack(‘Button1‘,‘‘)
例如下面的樣子
<input type="button" name="Button1" value="Button1" onclick="javascript:__doPostBack(‘Button1‘,‘‘)" id="Button1" />
===============================================================================================
這地方可看令一篇博文:http://www.cnblogs.com/Silicon-Fado/archive/2009/04/21/1440437.html
只有兩個Web Server Control 會自己觸發頁面的PostBack,其它的所有控件都是通過__doPostBack函數觸發頁面的PostBack,頁面解析時回將該類生成一個__doPostBack(eventTarget, eventArgument)方法。eventTarget是引起回送的控件的ID,eventArgument是回調參數(與控件相關的附加數據)。這兩個參數分別由隱藏的兩個表單域__ EVENTTARGET和__ EVENTARGUMENT保存。使用這兩個隱藏的表單可以查找引起頁面回送的控件ID和回送時的參數。
當你觸發__doPostBack事件時,遍歷this.Request.Form.AllKeys,你查看到這兩個隱藏的表單。
由於最終呈現給瀏覽器的內容都是html內容,采用asp.net技術也不能例外.要實現webcontrol的postback機制.只能在原來的submit上做文章。
我看到,asp.net現在頁面上添加了兩個hidden input,這兩個input分別用來存放觸發postback的control的ID和參數.這就是我們大部分人認識到的:
__doPostBack(obj1,obj2)的第一個參數是控件ID,第二個參數是postback的參數.然後就可以在後臺用Request.Form["__EVENTTARGET"]和Request.Form["__EVENTARGUMENT"]取得控件ID和參數.
很簡單就實現了看似很神奇,以為內部有什麽高深的處理的過程!如此輕巧的實現了asp.net的postback機制,佩服佩服!只要我們看懂了上邊的代碼,對__doPostBack的使用就應該不是什麽難事了.可以說__doPostBack就是這麽簡單的一回事.-_-||
不過,另外要註意的就是asp.net的webcontrols中,Button和ImgButton是異類,它們不是利用__doPostBack來實現postback的.為什麽這樣,可能因為Button在html中本來就是有觸發submit事件的功能吧.asp.net不過是要令原來html中一些不能觸發submit的東西submit,才弄出了__doPostBack來實現.對於原來就能submit的Button,又何必多此一舉呢.
如上寫法可以在後臺找到Button.為什麽這樣? 不知道,呵呵. 在Button的提交過程中,Button會將Button本身的ID作為Request.Form的一個Key,它的Value是Button的Text屬性值,回傳給服務器.所以可以在後臺循環Form.Keys取到所提交的Button,以執行相應的函數.ImgButton也差不多,不同就在於,它不是用ImageButton的ID作為Request.Form的Key,它是用ImageButton的ID加上.x和.y作為Key,在Request.Form添加兩上鍵值對,這兩個鍵值應該是對應ImageButton的圖片大小的,了解了這個規律後,我們仍然可以通過一定的方式得到是否是由ImageButton引發的PostBack.
如下面的我寫的一個簡單頁面的例子,
(1)頁面中的下拉列表呈現在hyml中是這樣的
<select name="DropDownList2" onchange="javascript:setTimeout('__doPostBack(\'DropDownList2\',\'\')', 0)" id="DropDownList2">
<option value="--請選擇--">--請選擇--</option>
<option value="家用家具1">家用家具1</option>
<option selected="selected" value="家用家具2">家用家具2</option>
<option value="家用家具3">家用家具3</option>
<option value="家用家具4">家用家具4</option>
</select>
可看到
onchange="javascript:setTimeout('__doPostBack(\'DropDownList2\',\'\')', 0)" id="DropDownList2">
此處下拉列表通過__doPostBack函數觸發頁面的PostBack,頁面解析時回將該類生成一個__doPostBack(eventTarget, eventArgument)方法。
(2)對於按鈕呢,則是這樣的
<input type="submit" name="Button1" value="確認" id="Button1" />
按鈕沒有用到__doPostBack,原因是asp.net的webcontrols中,Button和ImgButton是異類,它們不是利用__doPostBack來實現postback的.為什麽這樣,可能因為Button在html中本來就是有觸發submit事件的功能吧.asp.net不過是要令原來html中一些不能觸發submit的東西submit,才弄出了__doPostBack來實現.對於原來就能submit的Button,又何必多此一舉呢.
===================================================================================================
當按鈕被點擊後,觸發了__doPostBack事件,_doPostBack事件把表單提交給Server, Server端通過__EVENTTARGET這個hidden field的值找到對應的Server端的Control.接下來Server查看Control是否實現調用Page的RaisePostBackEvent,這個函數的定義如下:
protected virtual void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
sourceControl.RaisePostBackEvent(eventArgument);
}
函數調用本控件內的
protected virtual void RaisePostBackEvent(string eventArgument)
{
base.ValidateEvent(this.UniqueID, eventArgument);
iif (this.CausesValidation)
{
this.Page.Validate(this.ValidationGroup);
}
this.OnClick(EventArgs.Empty);
this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
}
__doPostBack方法解析 __VIEWSTATE __EVENTTARGET __doPostBack __EVENTARGUMENT