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

GridView RowDataBound 動態控制 CommandField 顯示與啟用:依資料列條件隱藏編輯/刪除按鈕

     編輯:ASP.NET 基礎

情境說明

GridView 內建的 CommandField(編輯、刪除、選取按鈕)預設對所有資料列一視同仁。實務上常見需求:

  • 特定狀態(如「已結案」、「已刪除」)的列不得編輯/刪除。
  • 依權限決定目前使用者是否可見特定操作按鈕。
  • 自動產生流水號(跨分頁連續編號)。

本文透過 RowDataBound 事件,示範如何動態隱藏第 0 欄(CommandField)與第 7 欄(自訂按鈕),並依「價格欄位是否為空」決定編輯按鈕是否可見。

完整後端程式碼 (C#)

protected void gvMaterial_RowDataBound(object sender, GridViewRowEventArgs e)
{
    // 僅處理資料列與標題列
    if (e.Row.RowType == DataControlRowType.DataRow || e.Row.RowType == DataControlRowType.Header)
    {
        // 隱藏第 0 欄(假設為 CommandField 或選取按鈕)
        e.Row.Cells[0].Visible = false;
    }

    // 僅資料列需處理流水號與按鈕邏輯
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // 1. 產生跨分頁連續流水號
        e.Row.Cells[1].Text = (gvMaterial.PageIndex * gvMaterial.PageSize + e.Row.RowIndex + 1).ToString();

        // 2. 取得價格欄位值(第 4 欄),支援編輯模式與一般模式
        string price;
        try
        {
            // 編輯模式下,欄位內為 TextBox 控制項
            price = ((TextBox)e.Row.Cells[4].Controls[0]).Text;
        }
        catch
        {
            // 一般模式,直接取 Cell.Text
            price = e.Row.Cells[4].Text;
        }

        // 3. 依價格是否為空,動態顯示/隱藏第 7 欄的按鈕(假設為編輯/刪除按鈕)
        var btnContainer = e.Row.Cells[7].Controls[0] as Control; // 可能是 LinkButton / Button
        if (btnContainer != null)
        {
            btnContainer.Visible = !string.IsNullOrWhiteSpace(price) && price != " ";
        }
    }
}

關鍵技術點解析

技術點說明
RowDataBound 觸發時機 每一列資料繫結完成後引發,包含 Header、Footer、Pager、DataRow。務必判斷 e.Row.RowType。
跨分頁流水號公式 PageIndex * PageSize + RowIndex + 1,確保第 2 頁第 1 列顯示 11 (PageSize=10)。
編輯模式下的控制項存取 進入編輯模式時,BoundField 會轉為 TextBox 置於 Cell.Controls[0];一般模式則為 LiteralControl 或直接 Cell.Text。用 try/catch 或 is TextBox 判斷較稳健。
動態控制按鈕可見 CommandField 產生的按鈕同樣在 Cell.Controls 集合中,索引 0 通常為第一個按鈕(編輯),索引 1 為刪除等。設定 Visible = false 即可隱藏且不佔版面。
效能考量 RowDataBound 會逐列執行,避免在迴圈中查詢資料庫或做複雜運算;若邏輯複雜,建議在資料繫結前預先標記 ViewModel/DTO 的 CanEdit 屬性。

進階擴充:改用 TemplateField 完全掌控

若需更彈性的 UI(如圖示按鈕、Tooltip、客製確認對話框),建議將 CommandField 改為 TemplateField:

<asp:TemplateField HeaderText="操作">
    <ItemTemplate>
        <asp:LinkButton ID="btnEdit" runat="server" CommandName="Edit" Text="編輯"
            Visible='<%# !string.IsNullOrEmpty(Eval("Price").ToString()) %>' />
        <asp:LinkButton ID="btnDelete" runat="server" CommandName="Delete" Text="刪除"
            OnClientClick="return confirm('確定刪除?');" />
    </ItemTemplate>
</asp:TemplateField>
  • 直接在 Visible 屬性使用繫結運算式 <%# ... %>,無需 RowDataBound 寫法。
  • 搭配 CommandName 仍能觸發 GridView 內建 RowEditing/RowDeleting 事件。
  • 更易於單元測試與前端框架整合。

常見坑與除錯技巧

  1. Cell 索引錯位:AutoGenerateColumns="true" 或加入 RowNumber 會改變索引。建議關閉自動產生,明確宣告每個欄位,或用 e.Row.Cells.Cast<TableCell>().ToList().FindIndex(c => c.Controls.OfType<LinkButton>().Any()) 動態尋找。
  2. 編輯模式下隱藏按鈕導致無法更新:若在編輯模式隱藏 Update/Cancel 按鈕,使用者將無法送出/取消。需在 e.Row.RowState.HasFlag(DataControlRowState.Edit) 判斷時保留這兩顆按鈕。
  3. ViewState 過大:大量資料列且每列動態控制按鈕,會增加 ViewState。考慮關閉 GridView ViewState (EnableViewState="false") 並在每次 Request 重新繫結。

結語

善用 RowDataBound 事件搭配 Cell.Controls 集合,即可在伺服器端精細控制 GridView 每列的按鈕顯示狀態。對於單純「依資料值決定是否顯示」的需求,改用 TemplateField + 繫結運算式會更乾淨、可維護性更高。選擇哪種方式,視專案複雜度與團隊習慣而定。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved