GridView 操作中頻繁需求:取得使用者點擊行的索引,進而存取該行資料、控制項或執行業務邏輯。本文整理 8 種常見方法並分析適用場景。
<asp:TemplateField HeaderText="操作">
<ItemTemplate>
<asp:LinkButton ID="lbtnQianRu" runat="server"
CommandName="QianRu"
CommandArgument='<%# Eval("Id") %>'>簽入</asp:LinkButton>
<asp:LinkButton ID="lbtnQianChu" runat="server"
CommandName="QianChu">簽出</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
protected void gv_Company_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "QianRu")
{
// 透過 CommandSource 找到 LinkButton -> Parent (Cell) -> Parent (Row)
GridViewRow drv = ((GridViewRow)(((LinkButton)(e.CommandSource)).Parent.Parent));
int id = Convert.ToInt32(GridView1.DataKeys[drv.RowIndex].Value);
}
}
DataKeyNames="Id"GridViewRow drv = (GridViewRow)((LinkButton)e.CommandSource).NamingContainer; int id = Convert.ToInt32(GridView1.Rows[drv.RowIndex].Cells[0].Text);
NamingContainer 直接回傳實作 INamingContainer 的容器 (GridViewRow)Cells[索引] 取得儲存格文字protected void lbtnQianChu_Command(object sender, CommandEventArgs e)
{
LinkButton lb = (LinkButton)sender;
DataControlFieldCell dcf = (DataControlFieldCell)lb.Parent;
GridViewRow gvr = (GridViewRow)dcf.Parent;
lbtnQianChu.SelectedIndex = gvr.RowIndex;
}
OnCommand 而非 GridView RowCommandprotected void LinkButton1_Click(object sender, EventArgs e)
{
int row = ((GridViewRow)((LinkButton)sender).NamingContainer).RowIndex;
}
CommandArgument,需額外處理DropDownList ddl = (DropDownList)sender; GridViewRow gvr = (GridViewRow)ddl.NamingContainer; int id = int.Parse(GridView1.DataKeys[gvr.RowIndex][0].ToString()); int num = int.Parse(ddl.Text);
CommandName,必須靠 NamingContainerAutoPostBack="true"CheckBox chk = (CheckBox)sender; DataControlFieldCell dcf = (DataControlFieldCell)chk.Parent; GridViewRow gvr = (GridViewRow)dcf.Parent;
<asp:GridView ID="gvTest" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
DisplayIndex : <%# Container.DisplayIndex %> ||
DataItemIndex : <%# Container.DataItemIndex %><br />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Container.DisplayIndex:顯示索引 (含分頁)Container.DataItemIndex:資料項實際索引 (跨分頁連續)protected void gvInfo_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton lk1 = (LinkButton)e.Row.FindControl("lkbtn");
lk1.CommandArgument = e.Row.RowIndex.ToString(); // 寫入行索引
}
}
protected void gvInfo_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "ADD")
{
int index = Convert.ToInt32(e.CommandArgument);
string aa = gvInfo.Rows[index].Cells[1].Text;
}
}
| 場景 | 推薦方法 | 理由 |
|---|---|---|
| RowCommand 事件 + 需 DataKey | 方法一 | 標準做法,配合 DataKeyNames 最穩健 |
| RowCommand 事件 + 需 Cells 值 | 方法二 | NamingContainer 語意清晰,效能佳 |
| LinkButton 獨立 Command/Click 事件 | 方法三/四 | 事件綁定靈活,程式碼簡潔 |
| DropDownList/CheckBox 觸發 | 方法五/六 | 無 CommandName 唯一解 |
| 純前端顯示索引 | 方法七 | 零後端程式碼,效能最佳 |
| 高頻操作 + 追求效能 | 方法八 | 預綁定避免執行時遍歷 |
INamingContainer 介面標記命名容器,確保子控制項 UniqueID 唯一性。GridViewRow 實作此介面,使每行內的同名控制項 (如 "lbtnQianRu") 不會 ID 衝突。Control.NamingContainer 屬性向上尋找最近的命名容器,對 GridView 即為該行的 GridViewRow。
掌握這 8 種方法,能根據具體場景選擇最適合的取得行索引策略,提升開發效率與程式碼品質。