專案需求:CheckBox 需額外屬性 (enableflag、witowner) 供前端 JavaScript 讀取控制。原生 CheckBox 繼承 WebControl,屬性會輸出在外層 <span>,導致 <input> 無法取得。本文示範繼承 WebControl、組合原生 CheckBox、覆寫 RenderContents 實現完整功能與自訂屬性輸出。
CheckBox + Attributes.Add → 屬性落在 <span>,<input type="checkbox"> 無屬性。WebControl + Render 手寫 HTML → 難以維持 <span> 包裹、樣式、事件等原生行為。public class ExCheckBox : WebControl
{
private CheckBox chkCheckbox = new CheckBox();
// 1. 暴露原生屬性/事件
public bool Checked { get => chkCheckbox.Checked; set => chkCheckbox.Checked = value; }
public string Text { get => chkCheckbox.Text; set => chkCheckbox.Text = value; }
public event EventHandler CheckedChanged { add => chkCheckbox.CheckedChanged += value; remove => chkCheckbox.CheckedChanged -= value; }
// 2. 自訂屬性
public bool EnableFlag { get; set; }
public string WitOwner { get; set; }
// 3. 核心:覆寫 RenderContents,讓 span 包裹 input + label
protected override void RenderContents(HtmlTextWriter writer)
{
SetCustomAttributes(); // 將自訂屬性寫入 chkCheckbox.Attributes
if (this.TextAlign == TextAlign.Right)
{
chkCheckbox.ID = ClientID + "_checkbox";
chkCheckbox.RenderControl(writer);
writer.Write($"");
}
else
{
writer.Write($"");
chkCheckbox.ID = ClientID + "_checkbox";
chkCheckbox.RenderControl(writer);
}
}
private void SetCustomAttributes()
{
chkCheckbox.Attributes["witowner"] = WitOwner ?? "true";
chkCheckbox.Attributes["enableflag"] = EnableFlag.ToString().ToLower();
// 其他原生屬性同步
chkCheckbox.Enabled = Enabled;
chkCheckbox.CssClass = CssClass;
chkCheckbox.ToolTip = ToolTip;
}
}
<span> (由 WebControl.Render 輸出) 包裹內容,樣式、ID、事件正常運作。<input>,保留 ViewState、PostBack、驗證等完整行為。<input> 上,前端 document.getElementById('...').getAttribute('witowner') 即可讀取。<cc1:ExCheckBox ID="chkAgree" runat="server" Text="同意條款"
EnableFlag="true" WitOwner="user123"
OnCheckedChanged="chkAgree_CheckedChanged" AutoPostBack="true" />
<script>
var chk = document.getElementById('<%= chkAgree.ClientID %>_checkbox');
console.log(chk.getAttribute('witowner')); // "user123"
</script>