ASP.NET Web Forms 採用**事件驅動**程式模型,頁面與控制項在生命週期各階段引發事件,開發者透過事件處理函數回應使用者互動。本文系統解析 Page_Load、IsPostBack、事件綁定方式、自動事件連結、PostBack 觸發流程與最佳實務。
<script runat="server">
protected void Page_Load(object sender, EventArgs e) {
// 頁面每次載入(含 PostBack)都會執行
lblTime.Text = "目前時間:" + DateTime.Now.ToString();
}
</script>
Load 階段,在 LoadViewState、LoadPostData 之後protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
// 僅初次請求執行:資料繫結、下拉選單填充、初始化設定
BindDropdownList();
LoadUserPreferences();
}
// 每次請求都執行:狀態恢復、通用邏輯
UpdateVisitCounter();
}
false:初次 GET 請求、書籤開啟、Response.Redirect 導向true:Button Click、LinkButton、AutoPostBack 控制項觸發、__doPostBack()、跨頁面 PostBack<script runat="server">
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
lblServerTime.Text = "伺服器時間(初次載入):" + DateTime.Now.ToLongTimeString();
}
}
protected void btnRefresh_Click(object sender, EventArgs e) {
lblClickTime.Text = "按鈕點擊時間:" + DateTime.Now.ToLongTimeString();
// lblServerTime 不會更新,因為 IsPostBack=true
}
</script>
<form runat="server">
<asp:Label ID="lblServerTime" runat="server" /><br/>
<asp:Label ID="lblClickTime" runat="server" /><br/>
<asp:Button ID="btnRefresh" Text="重新整理時間" runat="server" OnClick="btnRefresh_Click" />
</form>
<asp:Button ID="btn1" runat="server" Text="按鈕1" OnClick="btn1_Click" />
<asp:TextBox ID="txt1" runat="server" AutoPostBack="true" OnTextChanged="txt1_TextChanged" />
protected void Page_Init(object sender, EventArgs e) {
btn2.Click += new EventHandler(btn2_Click);
txt2.TextChanged += new EventHandler(txt2_TextChanged);
// Lambda 語法 .NET 3.5+
btn3.Click += (s, e) => { lbl.Text = "Lambda 綁定"; };
}
<%@ Page AutoEventWireup="true" %> <-- 預設開啟
Page_Load、Page_Init、Page_PreRender 等生命週期事件自動連結ControlID_EventName(如 btnSubmit_Click)需手動綁定或宣告式AutoEventWireup="false" 可提升效能,需手動綁定所有事件__VIEWSTATE、__EVENTTARGET、__EVENTARGUMENT)Init → LoadViewState → LoadPostData → Load (Page_Load)__EVENTTARGET 找到觸發控制項btn_Click、txt_TextChanged)PreRender → SaveViewState → Render → 回傳 HTML| 欄位名稱 | 用途 |
|---|---|
| __VIEWSTATE | 視圖狀態資料 |
| __EVENTTARGET | 觸發 PostBack 的控制項 UniqueID |
| __EVENTARGUMENT | 事件參數(如分頁索引、排序運算式) |
| __LASTFOCUS | 最後擁有焦點的控制項 |
| 階段 | 事件/方法 | 主要用途 | IsPostBack |
|---|---|---|---|
| 初始化 | PreInit | 動態建立控制項、設定 Master Page、Theme | false/true |
| Init | 控制項初始化、讀取 ControlState | false/true | |
| InitComplete | 初始化完成、ViewState 追蹤啟動 | false/true | |
| 載入 | PreLoad | 載入前準備 | false/true |
| Load (Page_Load) | 主要業務邏輯、資料繫結 | false/true | |
| LoadComplete | 載入完成 | false/true | |
| 事件處理 | PostBack 事件 | Button_Click、TextChanged 等 | true |
| 呈現準備 | PreRender | 最後修改控制項狀態、資料繫結確認 | false/true |
| PreRenderComplete | DataBind 完成、ViewState 最終確定 | false/true | |
| 儲存 | SaveViewState | 序列化 ViewState | true |
| SaveControlState | 序列化 ControlState | true | |
| 渲染 | Render | 產生 HTML 輸出 | false/true |
| 釋放 | Unload | 清理資源、關閉連線 | false/true |
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
gvData.DataSource = GetData();
gvData.DataBind();
}
}
protected void Page_Init(object sender, EventArgs e) {
// 動態控制項必須在 Init 階段重建,以參與 ViewState/PostData
for (int i = 0; i < DynamicCount; i++) {
TextBox txt = new TextBox { ID = "txtDynamic_" + i };
phContainer.Controls.Add(txt);
}
}
protected void Page_PreRender(object sender, EventArgs e) {
// 所有事件處理完畢,最後統一調整 UI 狀態
btnSave.Enabled = HasEditPermission;
pnlAdmin.Visible = IsAdmin;
lblTotal.Text = "共 " + GetTotalCount() + " 筆";
}
AutoEventWireup="true" 且程式碼又手動綁定 this.Load += Page_LoadPage_Init 重建、ID 不一致、ViewState 關閉runat="server" 缺失、JavaScript 錯誤阻擋 __doPostBackPage_Init,事件綁定同步進行Page_PreRenderAutoEventWireup 提升效能Page.IsCallback 區分一般 PostBack 與 Callback(如 GridView 回呼排序)Page.LoadComplete 統一處理跨控制項相依邏輯事件驅動模型是 Web Forms 開發的靈魂,精通 Page_Load/IsPostBack/生命週期/事件綁定機制,能精準控制程式碼執行時機,建構邏輯清晰、效能優異的 Web 應用。下一節將介紹伺服器控制項分類:HTML 伺服器控制項、Web 伺服器控制項、驗證控制項。