許多開發者對 Page.RegisterRequiresPostBack 感到困惑:官方文件僅說「註冊需回發處理的控件」,實際該如何、何時使用?本文從原始碼層面揭示資料回發核心機制,釐清 IPostBackDataHandler、LoadPostData、RaisePostDataChangedEvent 與頁面生命週期的精確關係。
需實現資料回發 (如輸入控件值變更偵測) 的控件必須實現此介面:
public interface IPostBackDataHandler
{
// 載入客戶端回發資料,比較新舊值,回傳 true 表示值已變更
bool LoadPostData(string postDataKey, NameValueCollection postCollection);
// 值已變更時引發事件 (如 TextChanged)
void RaisePostDataChangedEvent();
}
public void RegisterRequiresPostBack(Control control)
{
// 1. 強制檢查:控件或其 Adapter 必須實現 IPostBackDataHandler
if (!(control is IPostBackDataHandler))
{
IPostBackDataHandler dataHandler = control._adapter as IPostBackDataHandler;
if (dataHandler == null)
throw new HttpException(SR.GetString(SR.Ctrl_not_data_handler));
}
// 2. 延遲初始化儲存清單
if (_registeredControlsThatRequirePostBack == null)
_registeredControlsThatRequirePostBack = new ArrayList();
// 3. 關鍵:儲存控件的 UniqueID (而非 ClientID)
_registeredControlsThatRequirePostBack.Add(control.UniqueID);
}
Request.Form 的鍵值為控件的 name 屬性,ASP.NET 渲染時 name = UniqueID (含冒號分隔),故以 UniqueID 為鍵查找回發資料。Page_PreRender 之前 呼叫,否則錯過回發資料載入階段。LoadPostData (透過 UniqueID 從 Request.Form 取值、比較)。true → 頁面稍後自動呼叫 RaisePostDataChangedEvent。RaisePostDataChangedEvent 內部引發 TextChanged 等事件。public class MyTextBox : TextBox, IPostBackDataHandler
{
public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
string postedValue = postCollection[postDataKey];
string currentValue = this.Text;
if (postedValue != currentValue)
{
this.Text = postedValue;
return true; // 值已變更,稍後引發 TextChanged
}
return false;
}
public void RaisePostDataChangedEvent()
{
OnTextChanged(EventArgs.Empty); // 引發標準事件
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Page.RegisterRequiresPostBack(this); // 關鍵註冊
}
}
| 誤區 | 正確認知 |
|---|---|
| 所有控件都需呼叫 RegisterRequiresPostBack | 僅實作 IPostBackDataHandler 的控件 (輸入類) 需要;Button 等觸發事件類控件實作 IPostBackEventHandler,另套機制 |
| 在 Page_Load 註冊即可 | 必須在 PreRender 前,建議在 OnPreRender 覆寫中註冊 |
| ClientID 與 UniqueID 可互換 | 回發資料鍵值為 UniqueID (name 屬性),ClientID 僅供客戶端腳本使用 |
RegisterRequiresPostBack 是 ASP.NET 資料回發管線的「入口登記簿」。理解其儲存 UniqueID、配合 IPostBackDataHandler 雙階段處理 (載入比較 → 事件引發) 的機制,是開發高品質自訂輸入控件的核心功力。