例如:不同角色顯示不同儀表板、A/B 測試切換版本、外掛式架構動態載入功能模組。Page.LoadControl 是核心 API,配合 PlaceHolder 容器實現運行時組合。
<asp:PlaceHolder ID="OperContent" runat="server" />
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
LoadUserControlByRole();
}
}
private void LoadUserControlByRole() {
string controlPath = GetControlPathByRole(); // 例: "~/Controls/AdminDashboard.ascx"
// 1. 載入控制項實例
Control uc = Page.LoadControl(controlPath);
// 2. 設定唯一 ID (關鍵:否則 ViewState/事件綁定失效)
uc.ID = "DynamicControl_" + Guid.NewGuid().ToString("N").Substring(0, 8);
// 3. 加入容器
OperContent.Controls.Add(uc);
}
private string GetControlPathByRole() {
// 實際依 Session/Role/Claims 決定
return User.IsInRole("Admin") ? "~/Controls/AdminDashboard.ascx" : "~/Controls/UserDashboard.ascx";
}
若需呼叫 UserControl 的公用屬性/方法,需轉型:
// 定義介面或基類
public interface IDashboard {
void RefreshData(DateTime date);
string Title { get; set; }
}
// UserControl 實作介面
public partial class AdminDashboard : UserControl, IDashboard { ... }
// 動態載入並強型別操作
Control uc = Page.LoadControl("~/Controls/AdminDashboard.ascx");
if (uc is IDashboard dashboard) {
dashboard.Title = "管理員儀表板";
dashboard.RefreshData(DateTime.Today);
}
OperContent.Controls.Add(uc);
| 問題 | 原因 | 解決 |
|---|---|---|
| Postback 後控制項消失 | 動態控制項需在每次請求重建 | 在 Page_Init 或 Page_Load (IsPostBack 也要) 重建,且 ID 必須一致 |
| 事件不觸發 | ID 不一致導致 ViewState 無法對應 | 固定 ID:uc.ID = "DynamicDashboard"; (不可含隨機值) |
| 樣式/Script 不生效 | UserControl 內的 RegisterStartupScript 需在載入後執行 | 確保 ScriptManager 存在,或手動註冊腳本 |
| 巢狀 MasterPage 路徑錯誤 | 相對路徑解析異常 | 使用 VirtualPathUtility.ToAbsolute("~/Controls/...") 或 ResolveUrl |
protected void Page_Init(object sender, EventArgs e) {
// 1. 最早重建動態控制項 (確保 ViewState/事件正常)
RebuildDynamicControls();
}
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
// 2. 首次載入才設定初始資料
InitializeDynamicControls();
}
}
private void RebuildDynamicControls() {
string controlPath = ViewState["DynamicControlPath"]?.ToString();
if (!string.IsNullOrEmpty(controlPath)) {
Control uc = Page.LoadControl(controlPath);
uc.ID = "DynamicControl"; // 固定 ID
OperContent.Controls.Add(uc);
}
}
private void InitializeDynamicControls() {
string path = GetControlPathByRole();
ViewState["DynamicControlPath"] = path; // 記住路徑供 Postback 重建
RebuildDynamicControls();
// 設定初始資料...
if (OperContent.Controls[0] is IDashboard dash) dash.RefreshData(DateTime.Today);
}
Page.LoadControl + PlaceHolder 是 ASP.NET WebForms 動態組合 UI 的標準做法。核心在於 固定 ID 確保 Postback 重建一致性、在 Page_Init 重建控制項、ViewState 保存路徑資訊。掌握這三點,即可構建靈活、可維護的動態頁面架構。