前端頁面 (Default.aspx)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
OnPageIndexChanging="GridView1_PageIndexChanging"
OnRowCancelingEdit="GridView1_RowCancelingEdit"
OnRowEditing="GridView1_RowEditing"
OnRowUpdating="GridView1_RowUpdating"
OnRowDeleting="GridView1_RowDeleting"
OnSelectedIndexChanging="GridView1_SelectedIndexChanging"
DataKeyNames="Num">
<Columns>
<asp:TemplateField HeaderText="編號" Visible="False">
<ItemTemplate>
<asp:Label ID="lblNum" runat="server" Text='<%# Eval("Num") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="姓名">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Eval("TableName") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtTableName" runat="server" Text='<%# Eval("TableName") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="地址">
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Eval("TextName") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtTextName" runat="server" Text='<%# Eval("TextName") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:CommandField HeaderText="選取" ShowSelectButton="True" />
<asp:CommandField HeaderText="編輯" ShowEditButton="True" />
<asp:CommandField HeaderText="刪除" ShowDeleteButton="True" />
</Columns>
</asp:GridView>
<asp:Button ID="btnAdd" runat="server" Text="新增" OnClick="btnAdd_Click" />
後端程式碼 (Default.aspx.cs)
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) GridViewBind();
}
private void GridViewBind()
{
string sql = "SELECT Num, TableName, TextName FROM dbo.GroupType_Demo";
try
{
GridView1.DataSource = SqlHelper.ExecuteDataset(SqlHelper.GetConnSting(), CommandType.Text, sql).Tables[0];
GridView1.DataBind();
}
catch (Exception ex) { /* 記錄日誌 */ }
}
// 分頁
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridViewBind();
}
// 取消編輯
protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
GridView1.EditIndex = -1;
GridViewBind();
}
// 進入編輯模式
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
GridViewBind();
}
// 更新資料
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int num = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);
string tableName = ((TextBox)GridView1.Rows[e.RowIndex].FindControl("txtTableName")).Text;
string textName = ((TextBox)GridView1.Rows[e.RowIndex].FindControl("txtTextName")).Text;
string sql = "UPDATE dbo.GroupType_Demo SET TableName=@TableName, TextName=@TextName WHERE Num=@Num";
// 建議使用參數化查詢防止 SQL Injection
int result = SqlHelper.ExecuteNonQuery(SqlHelper.GetConnSting(), CommandType.Text, sql,
new SqlParameter("@TableName", tableName),
new SqlParameter("@TextName", textName),
new SqlParameter("@Num", num));
ShowAlert(result > 0 ? "修改成功!" : "修改失敗!");
GridView1.EditIndex = -1;
GridViewBind();
}
// 刪除資料
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int num = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);
string sql = "DELETE FROM dbo.GroupType_Demo WHERE Num=@Num";
int result = SqlHelper.ExecuteNonQuery(SqlHelper.GetConnSting(), CommandType.Text, sql,
new SqlParameter("@Num", num));
ShowAlert(result > 0 ? "刪除成功!" : "刪除失敗!");
GridViewBind();
}
// 新增導向
protected void btnAdd_Click(object sender, EventArgs e)
{
Response.Redirect("~/Default_Add.aspx");
}
// 選取列
protected void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
btnAdd.Text = $"你選中了第 {e.NewSelectedIndex + 1} 行。";
}
private void ShowAlert(string msg)
{
ClientScript.RegisterStartupScript(GetType(), "alert", $"alert('{msg}');", true);
}
}
關鍵重點總結
- DataKeyNames="Num":必須設定主鍵欄位,才能在 RowUpdating/RowDeleting 中透過
DataKeys[e.RowIndex].Value 取得正確主鍵值
- EditItemTemplate:編輯模式下顯示的控制項 (TextBox),配合
ShowEditButton 自動切換
- FindControl:在 RowUpdating 中必須用
FindControl 取得編輯模式下的 TextBox 值
- 參數化查詢:原文使用字串串接 SQL,極易遭 SQL Injection,**務必改用參數化**
- !IsPostBack 判斷:Page_Load 中只在首次載入時綁定資料,避免 PostBack 覆蓋使用者編輯的值
效能優化建議
- 啟用分頁
AllowPaging="True" PageSize="20"
- 大量資料考慮使用
ObjectDataSource 或自訂分頁存儲程序
- 更新/刪除後重新綁定前,可先檢查
GridView1.EditIndex = -1 確保退出編輯模式