GridView 內建的 CommandField(編輯、刪除、選取按鈕)預設對所有資料列一視同仁。實務上常見需求:
本文透過 RowDataBound 事件,示範如何動態隱藏第 0 欄(CommandField)與第 7 欄(自訂按鈕),並依「價格欄位是否為空」決定編輯按鈕是否可見。
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 屬性。 |
若需更彈性的 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 事件。AutoGenerateColumns="true" 或加入 RowNumber 會改變索引。建議關閉自動產生,明確宣告每個欄位,或用 e.Row.Cells.Cast<TableCell>().ToList().FindIndex(c => c.Controls.OfType<LinkButton>().Any()) 動態尋找。e.Row.RowState.HasFlag(DataControlRowState.Edit) 判斷時保留這兩顆按鈕。EnableViewState="false") 並在每次 Request 重新繫結。善用 RowDataBound 事件搭配 Cell.Controls 集合,即可在伺服器端精細控制 GridView 每列的按鈕顯示狀態。對於單純「依資料值決定是否顯示」的需求,改用 TemplateField + 繫結運算式會更乾淨、可維護性更高。選擇哪種方式,視專案複雜度與團隊習慣而定。