自訂伺服器控制項封裝 UI 與邏輯,提供設計時支援(工具箱、屬性視窗)、ViewState 管理、事件模型,可跨專案重用,是元件化開發核心。
本範例建立 `CheckBoxColumn` 控制項,用於 `DataGrid` 中顯示核取方塊列,支援資料繫選、自動回發、選取變更事件。
實作 `ITemplate.InstantiateIn` 動態建立 `CheckBox` 控制項並綁定事件:
internal class CheckBoxItem : ITemplate
{
private string _name;
private bool _readOnly;
private bool _autoPostBack;
public event EventHandler CheckedChanged;
public CheckBoxItem(bool editable, string name)
{
_name = name;
_readOnly = !editable;
}
void ITemplate.InstantiateIn(Control container)
{
CheckBox chk = new CheckBox();
chk.ID = _name;
chk.Enabled = !_readOnly;
chk.AutoPostBack = _autoPostBack;
chk.DataBinding += BindData;
chk.CheckedChanged += OnCheckChanged;
container.Controls.Add(chk);
}
private void BindData(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
DataGridItem item = (DataGridItem)chk.NamingContainer;
// 從資料項取得值繫結至 Checked 屬性
object val = DataBinder.Eval(item.DataItem, _name);
chk.Checked = (val != null && val != DBNull.Value) && Convert.ToBoolean(val);
}
private void OnCheckChanged(object sender, EventArgs e)
{
CheckedChanged?.Invoke(sender, e);
}
}
繼承 `DataGridColumn`,覆寫 `InitializeCell`、`Initialize` 等方法:
public class CheckBoxColumn : DataGridColumn
{
private string _dataField;
private bool _readOnly;
private bool _autoPostBack;
public string DataField { get => _dataField; set => _dataField = value; }
public bool ReadOnly { get => _readOnly; set => _readOnly = value; }
public bool AutoPostBack { get => _autoPostBack; set => _autoPostBack = value; }
public override void InitializeCell(TableCell cell, int columnIndex, ListItemType itemType)
{
base.InitializeCell(cell, columnIndex, itemType);
if (itemType == ListItemType.Item || itemType == ListItemType.AlternatingItem || itemType == ListItemType.EditItem)
{
CheckBoxItem template = new CheckBoxItem(!_readOnly, _dataField);
template.AutoPostBack = _autoPostBack;
template.CheckedChanged += (s, e) => OnColumnCheckChanged(s, e);
cell.Controls.Add(new LiteralControl(" ")); // 佔位
cell.Controls[0] = new TemplateControlWrapper(template); // 簡化:實際需正確處理 Template
}
else if (itemType == ListItemType.Header)
{
cell.Text = HeaderText;
}
}
// 事件轉發
public event EventHandler ColumnCheckChanged;
protected virtual void OnColumnCheckChanged(object sender, EventArgs e)
{
ColumnCheckChanged?.Invoke(this, e);
}
}
<asp:DataGrid ID="dg" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundColumn DataField="ProductName" HeaderText="產品" />
<cc:CheckBoxColumn DataField="IsActive" HeaderText="啟用" AutoPostBack="True"
OnColumnCheckChanged="dg_CheckChanged" />
</Columns>
</asp:DataGrid>
protected void dg_CheckChanged(object sender, EventArgs e)
{
// 處理核取方塊變更邏輯
}
自訂伺服器控制項雖開發門檻較高,但能將重複 UI 邏輯封裝為高階元件,提升團隊開發效率與程式碼品質。掌握 `ITemplate`、`DataGridColumn`、`CompositeControl` 等基類是關鍵。