ASP.NET 2.0+ 以 GridView 取代舊版 DataGrid,功能更強、API 更一致。本文整理 GridView 核心功能實作,包含資料綁定、分頁、排序、刪除、編輯更新,所有範例均以 SqlDataSource / DataSet 示範。
DataKeyNames 指定唯一識別欄位(通常為主鍵),支援多欄位複合鍵。
<asp:GridView ID="gvEmployees" runat="server"
DataKeyNames="EmployeeID"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="編號" />
<asp:BoundField DataField="FirstName" HeaderText="名字" />
<asp:BoundField DataField="LastName" HeaderText="姓氏" />
<asp:BoundField DataField="Title" HeaderText="職稱" />
<asp:BoundField DataField="BirthDate" HeaderText="生日" DataFormatString="{0:yyyy-MM-dd}" />
<asp:CommandField ShowEditButton="True" ShowDeleteButton="True" />
</Columns>
</asp:GridView>
// 在 RowDeleting、RowUpdating 等事件中 string empId = gvEmployees.DataKeys[e.RowIndex].Value.ToString(); // 或多鍵值 // string val = gvEmployees.DataKeys[e.RowIndex]["EmployeeID"].ToString();
private void BindGrid()
{
using (SqlConnection conn = DB.CreateConnection())
{
SqlDataAdapter da = new SqlDataAdapter(
"SELECT EmployeeID, FirstName, LastName, Title, BirthDate FROM Employees", conn);
DataSet ds = new DataSet();
da.Fill(ds, "Emp");
gvEmployees.DataSource = ds.Tables["Emp"];
gvEmployees.DataBind();
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) BindGrid();
}
<asp:GridView ...
AllowPaging="True"
PageSize="10"
PagerSettings-Mode="NumericFirstLast"
PagerStyle-CssClass="pagination" />
protected void gvEmployees_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvEmployees.PageIndex = e.NewPageIndex;
BindGrid(); // 重新綁定
}
<asp:GridView ... AllowSorting="True" />
protected void gvEmployees_Sorting(object sender, GridViewSortEventArgs e)
{
// 1. 取得/切換排序方向
string sortDir = "ASC";
if (ViewState["SortExpr"]?.ToString() == e.SortExpression)
{
sortDir = ViewState["SortDir"]?.ToString() == "ASC" ? "DESC" : "ASC";
}
ViewState["SortExpr"] = e.SortExpression;
ViewState["SortDir"] = sortDir;
// 2. 查詢並排序
using (SqlConnection conn = DB.CreateConnection())
{
SqlDataAdapter da = new SqlDataAdapter(
"SELECT EmployeeID, FirstName, LastName, Title, BirthDate FROM Employees", conn);
DataSet ds = new DataSet();
da.Fill(ds, "Emp");
// DataView 支援排序
ds.Tables["Emp"].DefaultView.Sort = $"{e.SortExpression} {sortDir}";
gvEmployees.DataSource = ds.Tables["Emp"].DefaultView;
gvEmployees.DataBind();
}
}
protected void gvEmployees_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
string empId = gvEmployees.DataKeys[e.RowIndex].Value.ToString();
using (SqlConnection conn = DB.CreateConnection())
{
SqlCommand cmd = new SqlCommand("DELETE FROM Employees WHERE EmployeeID = @Id", conn);
cmd.Parameters.AddWithValue("@Id", empId);
conn.Open();
cmd.ExecuteNonQuery();
}
BindGrid();
}
// 進入編輯模式
protected void gvEmployees_RowEditing(object sender, GridViewEditEventArgs e)
{
gvEmployees.EditIndex = e.NewEditIndex;
BindGrid();
}
// 取消編輯
protected void gvEmployees_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
gvEmployees.EditIndex = -1;
BindGrid();
}
// 更新資料
protected void gvEmployees_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string empId = gvEmployees.DataKeys[e.RowIndex].Value.ToString();
// 從編輯行的控件取值:Cells[欄位索引].Controls[0] 強轉為 TextBox
string lastName = ((TextBox)gvEmployees.Rows[e.RowIndex].Cells[2].Controls[0]).Text;
string title = ((TextBox)gvEmployees.Rows[e.RowIndex].Cells[3].Controls[0]).Text;
// BirthDate 需解析日期
using (SqlConnection conn = DB.CreateConnection())
{
SqlCommand cmd = new SqlCommand(
"UPDATE Employees SET LastName=@LastName, Title=@Title WHERE EmployeeID=@Id", conn);
cmd.Parameters.AddWithValue("@LastName", lastName);
cmd.Parameters.AddWithValue("@Title", title);
cmd.Parameters.AddWithValue("@Id", empId);
conn.Open();
cmd.ExecuteNonQuery();
}
gvEmployees.EditIndex = -1;
BindGrid();
}
使用 TemplateField 可自訂編輯介面(下拉選單、日期選擇器、驗證控件等):
<asp:TemplateField HeaderText="職稱">
<ItemTemplate>
<%# Eval("Title") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlTitle" runat="server"
SelectedValue='<%# Bind("Title") %>'
DataSourceID="SqlDataSourceTitles"
DataTextField="TitleName" DataValueField="TitleName" />
</EditItemTemplate>
</asp:TemplateField>

| 特性 | Repeater | DataList | GridView |
|---|---|---|---|
| HTML 輸出 | 完全自訂 | Table 流式 | Table 表格式 |
| 內建編輯/刪除 | 無 | 有 | 完整 |
| 內建分頁/排序 | 無 | 無 | 有 |
| DataKeyNames | 無 | 無 | 有 |
| 適用場景 | 唯讀清單、高度客製化 | 簡單編輯、重複式版面 | 後台管理、完整 CRUD |
using 區塊包裹 Connection/Command/AdapterEnableViewState="False",配合每次 PostBack 重新綁定ROW_NUMBER() / OFFSET FETCH)而非前端分頁ItemTemplate/EditItemTemplate 是客製化關鍵GridView 封裝了後台管理最常需的分頁、排序、編輯、刪除功能,搭配 DataKeyNames、TemplateField、事件模型,能快速構建功能完整的資料維護介面。理解其事件生命週期(RowEditing → RowUpdating → RowUpdated)與資料綁定時機,是 ASP.NET Web Forms 開發者的必修課。