GridView 欄位類型速查
| 欄位類型 | 用途 | 適用場景 |
| BoundField | 簡單資料繫結顯示文字 | 唯讀顯示、字串、數字、日期 |
| CheckBoxField | 布林值核取方塊 | True/False 欄位顯示與編輯 |
| CommandField | 內建命令按鈕 | 編輯、刪除、選取、分頁、排序 |
| ButtonField | 自訂按鈕 | 自訂命令名稱/引數 |
| HyperLinkField | 超連結 | 導向詳細頁、外部連結 |
| ImageField | 圖片顯示 | 圖片 URL 欄位 |
| TemplateField | 完全自訂樣板 | 複雜 UI、多控制項、條件顯示、編輯介面 |
TemplateField 樣板類型完整對照
| 樣板 | 用途 | 啟用條件 |
| ItemTemplate | 一般資料列顯示 | 永遠 |
| AlternatingItemTemplate | 交替資料列顯示 | 設定後生效 |
| EditItemTemplate | 編輯模式介面 | 進入編輯狀態 |
| InsertItemTemplate | 新增模式介面 | 搭配 DetailsView/FormView 或自訂新增 |
| HeaderTemplate | 自訂表頭 | 設定後取代 HeaderText |
| FooterTemplate | 自訂表尾 | ShowFooter="true" |
| PagerTemplate | 自訂分頁列 | PagerSettings.Mode="Template" |
實戰範例:Northwind Employees 完整 GridView
1. 資料來源設定
- SqlDataSource 連接 Northwind,選取 Employees 表:
EmployeeID, LastName, FirstName, Title, HireDate。
- 啟用 進階選項 → 產生 INSERT/UPDATE/DELETE 陳述式、使用開放式平行存取。
2. GridView 宣告式標記
<asp:GridView ID="gvEmployees" runat="server"
DataSourceID="sqlDsEmployees"
AutoGenerateColumns="False"
DataKeyNames="EmployeeID"
AllowPaging="True" PageSize="5"
AllowSorting="True"
OnRowEditing="gvEmployees_RowEditing"
OnRowUpdating="gvEmployees_RowUpdating"
OnRowCancelingEdit="gvEmployees_RowCancelingEdit"
OnRowDeleting="gvEmployees_RowDeleting">
<Columns>
<!-- 僅顯示:姓名合併顯示 -->
<asp:TemplateField HeaderText="姓名" SortExpression="LastName">
<ItemTemplate>
<%# Eval("LastName") + " " + Eval("FirstName") %>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtLastName" runat="server" Text='<%# Bind("LastName") %>' Width="80" />
<asp:TextBox ID="txtFirstName" runat="server" Text='<%# Bind("FirstName") %>' Width="80" />
<asp:RequiredFieldValidator ControlToValidate="txtLastName" Text="*" runat="server" />
<asp:RequiredFieldValidator ControlToValidate="txtFirstName" Text="*" runat="server" />
</EditItemTemplate>
</asp:TemplateField>
<!-- 職稱:下拉選單編輯 -->
<asp:TemplateField HeaderText="職稱" SortExpression="Title">
<ItemTemplate><%# Eval("Title") %></ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlTitle" runat="server"
SelectedValue='<%# Bind("Title") %>'
DataSourceID="sqlDsTitles" DataTextField="Title" DataValueField="Title"
AppendDataBoundItems="True">
<asp:ListItem Value="">--請選擇--</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
<!-- 到職日期:唯讀顯示,編輯用 Calendar -->
<asp:TemplateField HeaderText="到職日期" SortExpression="HireDate">
<ItemTemplate><%# Eval("HireDate", "{0:yyyy/MM/dd}") %></ItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="calHireDate" runat="server"
SelectedDate='<%# Bind("HireDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
<!-- 命令欄 -->
<asp:CommandField ShowEditButton="True" ShowDeleteButton="True"
HeaderText="操作" ButtonType="Link" />
</Columns>
<!-- 自訂表頭樣板 -->
<HeaderTemplate>
<tr style="background:#336699; color:white;">
<th>員工資料管理</th>
</tr>
</HeaderTemplate>
<!-- 自訂表尾:統計筆數 -->
<FooterTemplate>
<tr><td colspan="4">共 <%# ((GridView)Container.NamingContainer).Rows.Count %> 筆資料</td></tr>
</FooterTemplate>
</asp:GridView>
3. 後置程式碼事件處理
protected void gvEmployees_RowEditing(object sender, GridViewEditEventArgs e)
{
gvEmployees.EditIndex = e.NewEditIndex;
// GridView 會自動重新繫結 (DataSourceID 機制)
}
protected void gvEmployees_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
// 取得編輯列控制項值
GridViewRow row = gvEmployees.Rows[e.RowIndex];
TextBox txtLastName = (TextBox)row.FindControl("txtLastName");
TextBox txtFirstName = (TextBox)row.FindControl("txtFirstName");
DropDownList ddlTitle = (DropDownList)row.FindControl("ddlTitle");
Calendar calHireDate = (Calendar)row.FindControl("calHireDate");
// 更新參數會自動由 Bind 表達式填入,SqlDataSource 執行 UPDATE
gvEmployees.EditIndex = -1; // 結束編輯
}
protected void gvEmployees_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
gvEmployees.EditIndex = -1;
}
protected void gvEmployees_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
// 可在這裡加入刪除前確認、稽核日誌
// SqlDataSource 自動執行 DELETE
}
進階技巧
條件式顯示/隱藏控制項
<ItemTemplate>
<%# Eval("Title").ToString() == "Sales Representative" ?
"<span style='color:red'>" + Eval("Title") + "</span>" :
Eval("Title") %>
</ItemTemplate>
FooterTemplate 計算總計
<FooterTemplate>
<tr><td colspan="2">總計</td>
<td><%# GetTotalPrice((GridView)Container.NamingContainer) %></td></tr>
</FooterTemplate>
protected decimal GetTotalPrice(GridView gv)
{
decimal sum = 0;
foreach (GridViewRow row in gv.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
Label lbl = (Label)row.FindControl("lblPrice");
if (lbl != null) sum += decimal.Parse(lbl.Text);
}
}
return sum;
}
RowDataBound 動態調整
protected void gvEmployees_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView drv = (DataRowView)e.Row.DataItem;
DateTime hireDate = (DateTime)drv["HireDate"];
if (hireDate.Year < 1995)
e.Row.BackColor = System.Drawing.Color.LightYellow; // 資深員工高亮
}
}
自動套用格式與 CSS 隔離
- 智慧標籤 → 自動套用格式 → 選擇預設主題 (Professional, Colorful, Simple 等)。
- 產生的 CSS 類別:
.gvEmployees, .gvEmployees th, .gvEmployees .alt 等,可於外部 CSS 覆寫。
常見問題與解決
| 問題 | 原因 | 解決 |
| 編輯時 Calendar 不顯示選中日期 | Bind 表達式型別轉換、或 Calendar SelectedDate 未正確設定 | 確認資料型別為 DateTime、使用 <%# Bind("HireDate") %> 而非 Eval |
| FooterTemplate 不顯示 | GridView.ShowFooter 預設 false | 設定 ShowFooter="True" |
| 更新後資料不重新整理 | 未重設 EditIndex=-1、或 SqlDataSource 未正確執行 UPDATE | 檢查 RowUpdating 結束時 EditIndex=-1、檢查 SqlDataSource UpdateCommand 參數 |
結語
GridView 的 TemplateField 是 ASP.NET 2.0 最強大的資料呈現工具之一。善用 ItemTemplate、EditItemTemplate、HeaderTemplate、FooterTemplate 搭配 Eval/Bind、驗證控制項、下拉選單、Calendar 等元件,即可打造媲美桌面應用的豐富資料編輯體驗,且全然宣告式、極易維護。