ASP.NET WebForms 提供豐富的內建伺服器控制項,但實務上常需要「客製化外觀、行為或事件模型」的按鈕。透過繼承 WebControl 並實作 IPostBackEventHandler,即可打造功能完整、支援設計工具屬性視窗、可在工具箱拖曳使用的自訂 Button。本文完整展示從類別定義、屬性封裝、事件模型、標記渲染到頁面註冊使用的全流程。
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:MyButton runat=server></{0}:MyButton>")]
public class MyButton : WebControl, IPostBackEventHandler
{
// ---- Text 屬性:支援 ViewState、設計工具分類、預設值、區域化 ----
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text
{
get { return (string)ViewState["Text"] ?? string.Empty; }
set { ViewState["Text"] = value; }
}
// ---- Size 複雜屬性:內含 Width/Height,示範 DesignerSerializationVisibility ----
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Size Size
{
get
{
if (ViewState["Size"] == null) ViewState["Size"] = new Size();
return (Size)ViewState["Size"];
}
set { ViewState["Size"] = value; }
}
// ---- 指定輸出標籤為 <input> ----
protected override HtmlTextWriterTag TagKey => HtmlTextWriterTag.Input;
// ---- 初始化:設定 style、type、value、name(PostBack 必備)----
protected override void OnInit(EventArgs e)
{
Style.Add("width", Size.Width + "px");
Style.Add("height", Size.Height + "px");
Attributes.Add("type", "submit");
Attributes.Add("value", Text);
Attributes.Add("name", UniqueID); // PostBack 必須
base.OnInit(e);
}
protected override void RenderContents(HtmlTextWriter output)
{
// input 標籤無內容,故留空
}
// ---- 事件模型:標準 CLR 事件 + EventHandlerList ----
public delegate void ClickHandle();
private readonly object _eventKey = new object();
public event ClickHandle Click
{
add { Events.AddHandler(_eventKey, value); }
remove { Events.RemoveHandler(_eventKey, value); }
}
// ---- IPostBackEventHandler 實作:PostBack 觸發時引發 Click 事件 ----
public void RaisePostBackEvent(string eventArgument)
{
var handler = (ClickHandle)Events[_eventKey];
handler?.Invoke();
}
}
}
<input type="submit" ...>,符合按鈕語意。name=UniqueID 辨識觸發 PostBack 的控制項,缺少將導致事件不觸發。<%@ Register Assembly="MyControls" Namespace="MyControls" TagPrefix="cc1" %>
<cc1:MyButton ID="MyButton1" runat="server"
Text="我是一個單獨的提交按鈕(自定義伺服器)"
Size-Height="30" Size-Width="290"
OnClick="btnSubmit" />
protected void btnSubmit()
{
Response.Write("我是自定義伺服器控制項的點擊事件");
}
CommandName/CommandArgument 支援 Command 事件,符合 Repeater/GridView 按鈕慣例。IButtonControl 介面,提供 PostBackUrl、ValidationGroup、CausesValidation 等標準按鈕特性。<button> 而非 <input>,支援圖示、HTML 內容豐富化。OnClientClick),支援前端驗證或確認對話框。自訂伺服器控制項看似門檻高,實則遵循固定模式:繼承基類 → 定義屬性(ViewState) → 指定 TagKey → OnInit 設定屬性/事件必要屬性 → 實作介面事件 → 設計工具屬性裝飾。掌握此範本,即可打造任何商業級控制項,並完整整合進 Visual Studio 設計工具體驗。