ASP.NET組件設計Step by Step(6)
回傳事件映射到伺服器端事件
asp.net頁面如果是通過post請求到伺服器,架構將會遵行事件周期產生、調用控制項,而控制項(如果支援回傳)則將載入回傳資料,並且映射成控制項的伺服器端事件,就好像在重放客戶的客戶行為(客戶按下一個按鈕,卻引發伺服器端控制項的click事件)。其中的機制如何?
如果一個控制項需要處理回傳事件,那麼必須實現一個特定介面 IPostBackEventHandler介面:
public interface IPostBackEventHandler{
void RaisePostBackEvent(string eventArgument);
}
以及另外一個介面:
IPostBackDataHandler
{
bool LoadPostData( string postDataKey, NameValueCollection postCollection);
void RaisePostDataChangedEvent();
}
一旦控制項實現了這些介面,頁面架構就會自動在PostBack資料完成後,調用控制項的此介面IPostBackDataHandler。LoadPostData,從而讓控制項讀取post上來的資料。PostDataKey為PostBack資料中的命名鍵名,通過NameValueCollection[postDataKey]可以獲得頁面架構傳遞給控制項的值。控制項應當讀取此值,進行自己內部狀態更新,反映狀態變化。如果控制項返回真,表示伺服器控制項狀態改變,此時頁面架構會立即調用此控制項的RaisePostDataChangedEvent方法。此時,控制項應當自己定義該引發那些伺服器控制項對外提供的事件。這些事件往往是控制項編程者精心設計留給使用這控鍵的aspx編程者的代碼舞台。
至於另一個介面IPostBackEventHandler,也是回傳時候伺服器調用的介面。我們知道每一個控制項都有一個UniqueID,當用戶端觸發一個可以引起回傳的用戶端事件(譬如按下了submit按鈕),那麼自然HTTP Post資料到伺服器端,伺服器頁面架構進行到PostBack處理時候,會檢索控制項是否支援IpostBackEventHandler介面,並且尋找控制項的UniqueID發現支援就立即調用此介面的RaisePostBackEvent方法,表示UniqueID的控制項發生了一個需要捕獲的事件。很明顯,並非用戶端所有事件都可以投射到伺服器端,只能夠是能夠引發Post Back(也就是能夠提交表單資料到伺服器的事件)的事件和控制項。注意,這裡嚴格要求了UniqueID必須在伺服器端和用戶端對應一致,否則無法映射事件。
值得控制項編寫者注意的是,如果要實現介面,需要如下實現介面,而不是通常的僅僅介面方法名同名即可:
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
……
}
也就是說,介面針對頁面架構實現的,也由頁面架構調用。
另一方面,在用戶端,能夠引起回傳的實際上僅有2個HTML元素<inoput type=submit >和<input type=image,但是通過用戶端指令碼,其他用戶端事件也可導致回傳資料到伺服器端。Page類提供了一系列的方法來協助實現其他可引發回傳的途徑:
public string GetPostBackClientEvent(
Control control,
string argument
);
擷取對用戶端指令碼函數的引用,該函數在被調用時將導致伺服器回傳到表單。
public string GetPostBackClientHyperlink(
Control control,
string argument
);將 javascript: 追加到從 GetPostBackEventReference 調用的返回的開頭,從而使伺服器上可以進行超級連結回傳處理。
public string GetPostBackEventReference(Control);
public string GetPostBackEventReference(Control, string);
擷取對用戶端指令碼函數的引用,調用該函數將使伺服器
如果一個控制項確定通過以上方法確保用戶端引發回傳事件,那麼控制項引用頁將導致最終輸出到用戶端的HTML中包含指令碼,並且指令碼中藏有如下隱含變數:
<input type=”hidden” name=”__EVENTTARGET” value=””>
<input type=”hidden” name=”__EVENTARGUMENT” value=””>
<script language=”javascript”>
<!—
function __doPostBack(eventTarget,eventArgument)
{
var theform=document._ct10;
theform.__EVENTTARGET.value= eventTarget;
theform.__EVENTARGUMENT.value= eventArgument;
}
-- >
</script>
任何用戶端指令碼只要合法調用了__doPostBack方法即可實現回傳到伺服器端,並且伺服器端也知道了是引發了那一個UniqueID得控制項的事件。