拖放 Button 至 UserControl (EventModule.ascx),再放入頁面 (Default.aspx):
Button1.ID = "Button1" (程式碼邏輯識別碼)Button1.ClientID = "EventModule1_Button1" (瀏覽器端 HTML id 屬性)Button1.UniqueID = "EventModule1$Button1" (表單提交時的 name 屬性值)瀏覽器回傳表單資料時,**只有 name 屬性會被送回伺服器**,伺服器端透過 Request.Form["EventModule1$Button1"] 找到觸發事件的控制項。
<input type="submit" name="EventModule1$Button1" value="EventButton" id="EventModule1_Button1" />
name="EventModule1$Button1" → 對應 UniqueID,含命名容器分隔符 $。id="EventModule1_Button1" → 對應 ClientID,分隔符 _,供 JavaScript/CSS 選取。EventModule1$Button1=EventButton。ProcessPostData 階段,解析 Form 集合。FindControl("EventModule1$Button1") (內部實作)。FindControl 以 $ 分割:"EventModule1" → 找到 UserControl → "Button1" → 找到 Button。IPostBackEventHandler,呼叫 RaisePostBackEvent 觸發 Click 事件。頁面放置兩個 Button (Button1、Button2),點擊 Button1 後,Request.Form 僅包含 EventModule1$Button1,**不包含** Button2 的鍵值。這證明:
<input type="submit"> 其 name/value 會被送出。| 屬性 | 分隔符 | 用途 | 範例 |
|---|---|---|---|
| UniqueID | $ | 伺服器端尋找控制項、表單提交 name、Postback 事件路由 | ctl00$ContentPlaceHolder1$EventModule1$Button1 |
| ClientID | _ | 瀏覽器端 HTML id、JavaScript document.getElementById、CSS 選取器 | ctl00_ContentPlaceHolder1_EventModule1_Button1 |
| ID | 無 | 程式碼邏輯識別、FindControl 相對路徑 | Button1 |
Public Class MyCustomButton : Implements IPostBackEventHandler
Public Event Click As EventHandler
Protected Overrides Sub Render(writer As HtmlTextWriter)
' 輸出隱藏欄位攜帶命令參數
writer.Write("")
' 輸出可見按鈕
writer.Write("")
End Sub
Public Sub RaisePostBackEvent(eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
' eventArgument 即隱藏欄位 value
RaiseEvent Click(Me, New EventArgs())
End Sub
End Class
ASP.NET 頁面自動輸出兩個隱藏欄位:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
LinkButton、ImageButton、AutoPostBack=True 控制項:透過 __doPostBack('UniqueID', 'Argument') JavaScript 設定兩欄位值並提交表單。RaisePostBackEvent 讀取 Request.Form["__EVENTTARGET"] 找到控制項 UniqueID,再呼叫其 RaisePostBackEvent(argument)。| 症狀 | 原因 | 解決 |
|---|---|---|
| 動態控制項事件不觸發 | 建立時機晚於 ProcessPostData (需在 OnInit) | 移至 Page_Init / OnInit 建立,確保 ID 固定 |
| UserControl 內按鈕 Click 事件不觸發 | UserControl ID 變動導致 UniqueID 不匹配 | 固定 UserControl ID (勿動態產生 ID) |
| JavaScript 無法取得控制項 | 用 UniqueID 而非 ClientID | document.getElementById('<%= btn.ClientID %>') |
| __doPostBack 未定義 | 頁面無 ScriptManager/PostBack 控制項 | 確保頁面有至少一個 PostBack 控制項或手動註冊 |
ASP.NET 事件回傳機制建立在 **HTML 表單提交** 與 **命名容器層級 ID (UniqueID)** 之上。掌握 UniqueID (name/$)、ClientID (id/_)、ID 三者差異、Request.Form 解析流程、FindControl 遞迴邏輯、__doPostBack 隱藏欄位協定,即能從根本理解「為什麼點擊按鈕能精準觸發伺服器事件」,並快速排除動態控制項、UserControl、JavaScript 互動等常見回傳失效問題。