首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET GridView 動態新增欄位完整實作與分頁問題解決

     編輯:關於ASP.NET

在程式碼後置動態建立 GridView 欄位(TemplateField、BoundField 等),並解決動態欄位在分頁、PostBack 後消失或重複的常見問題。

動態建立 TemplateField 範例(含刪除按鈕)

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);
        }
    }
}

關鍵問題:分頁與 PostBack 後動態欄位消失

原因:GridView 動態欄位不會自動保存在 ViewState,每次 Request 都需重建。

解決原則:

  1. 在 Page_Init 或 Page_Load(IsPostBack 皆執行)重建所有動態欄位
  2. 重建順序與邏輯必須與首次載入完全一致
  3. 資料繫結 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();
    }
}

動態 BoundField 範例(依資料表欄位自動產生)

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();
}

效能與維護建議

  • 盡量使用靜態宣告(.aspx 標記)定義固定欄位,僅對真正動態的部分用程式碼建立
  • 將動態欄位建立邏輯封裝為獨立方法,便於單元測試
  • 大量資料時考慮 GridView.EnableViewState = false 搭配每次重新查詢繫結
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved