在程式碼後置動態建立 GridView 欄位(TemplateField、BoundField 等),並解決動態欄位在分頁、PostBack 後消失或重複的常見問題。
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
BuildDynamicColumns();
BindData();
} else {
// PostBack 時必須重建欄位,否則事件無法觸發
BuildDynamicColumns();
}
}
private void BuildDynamicColumns() {
// 重要:先清空現有動態欄位,避免重複
// 僅移除動態新增的欄位,保留靜態宣告的欄位
for (int i = gv.Columns.Count - 1; i >= 0; i--) {
if (gv.Columns[i] is TemplateField tf && tf.HeaderText == "刪除") {
gv.Columns.RemoveAt(i);
}
}
// 建立刪除按鈕欄位
TemplateField deleteField = new TemplateField();
deleteField.HeaderText = "刪除";
deleteField.ItemTemplate = new GridViewTemplate(ListItemType.Item, "Delete");
gv.Columns.Add(deleteField);
}
// 自訂 ITemplate 實作
public class GridViewTemplate : ITemplate {
private ListItemType _type;
private string _commandName;
public GridViewTemplate(ListItemType type, string commandName) {
_type = type; _commandName = commandName;
}
public void InstantiateIn(Control container) {
if (_type == ListItemType.Item) {
LinkButton lb = new LinkButton();
lb.Text = "刪除";
lb.CommandName = _commandName;
lb.CommandArgument = Container.DataItemIndex.ToString(); // 需在 DataBinding 事件設定
container.Controls.Add(lb);
}
}
}
原因:GridView 動態欄位不會自動保存在 ViewState,每次 Request 都需重建。
解決原則:
Page_Init 或 Page_Load(IsPostBack 皆執行)重建所有動態欄位BindData() 放在欄位重建之後protected void Page_Init(object sender, EventArgs e) {
// 最佳時機:Init 階段重建動態控制項,確保 ViewState 正常追蹤
BuildDynamicColumns();
}
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
BindData();
}
// PostBack 時不需再 BindData,除非資料異動
}
protected void gv_PageIndexChanging(object sender, GridViewPageEventArgs e) {
gv.PageIndex = e.NewPageIndex;
BindData(); // 重新繫結,動態欄位已在 Init 重建完成
}
protected void gv_RowCommand(object sender, GridViewCommandEventArgs e) {
if (e.CommandName == "Delete") {
int index = Convert.ToInt32(e.CommandArgument);
int dataKey = (int)gv.DataKeys[index].Value;
DeleteRecord(dataKey);
BindData();
}
}
private void BuildBoundColumns(DataTable dt) {
gv.Columns.Clear(); // 完全動態時可 Clear
foreach (DataColumn col in dt.Columns) {
BoundField bf = new BoundField();
bf.DataField = col.ColumnName;
bf.HeaderText = col.ColumnName;
bf.SortExpression = col.ColumnName;
gv.Columns.Add(bf);
}
// 最後再加入操作欄位
BuildDynamicColumns();
}
GridView.EnableViewState = false 搭配每次重新查詢繫結