Abstract
在.NET 1.x的DataGrid,可以在ItemCommand event的e.Item.ItemIndex獲得目前的RowIndex,但在.NET 2.0的GridView,卻無法使用這種方式在RowCommand event獲得RowIndex。
Motivation
為什麼需要在RowCommand event獲得RowIndex呢?通常一個Table的PK或FK並不會顯示在GridView上,而會設定在DataKeyNames property,然後再RowCommand event根據RowIndex讀出該row的PK或FK,所以第一步,必須先能在RowCommand獲得目前的RowIndex。
Introduction
.NET 1.x DataGrid
在.NET 1.x的DataGrid,若要使用LinkButton,一樣得放在TemplateColumn內,且ItemCommand event的e.Item.ItemIndex就可抓到RowIndex。
當在DataGrid點下FirstName後,會在下方的Label顯示LastName,LastName是此例的DataKey。
2 <% @ Import Namespace="System.Data.SqlClient" %>
3
4 <% @ Page Language="C#" %>
5
6 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
7
8 < script runat ="server" >
9/**//*
10(C) OOMusou 2007 http://oomusou.cnblogs.com
11
12Filename : DataGrid_DataKeyField.aspx
13Compiler : Visual Studio 2005 / C# 2.0 / ASP.NET 2.0
14Description : Demo how to get RowIndex in DataGrid's LinkButton
15Release : 06/26/2007 1.0
16*/
17 protected void Page_Load(object sender, EventArgs e) {
18 if (!IsPostBack)
19 DataGrid1_DataBind();
20 }
21
22 protected void DataGrid1_DataBind() {
23 string strSQL = "SELECT TOP 10 " +
24 "fname," +
25 "lname " +
26 "FROM employee";
27 SqlConnection con = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=pubs;Integrated Security=True");
28 SqlDataAdapter da = new SqlDataAdapter(strSQL, con);
29 DataSet ds = new DataSet();
30
31 try {
32 da.Fill(ds);
33 }
34 catch (Exception err) {
35 Response.Write(err.ToString());
36 return;
37 }
38 finally {
39 if ((con != null) && (con.State == ConnectionState.Open))
40 con.Close();
41 }
42
43 DataGrid1.DataSource = ds;
44 DataGrid1.DataKeyField = "lname";
45 DataGrid1.AutoGenerateColumns = false;
46 DataGrid1.DataBind();
47 }
48
49 protected void DataGrid1_ItemCommand(object source, DataGridCommandEventArgs e) {
50 if (e.CommandName == "Select")
51 Label1.Text = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
52 }
53 </ script >
54
55 < html xmlns ="http://www.w3.org/1999/xhtml" >
56 < head runat ="server" >
57 < title > Untitled Page </ title >
58 </ head >
59 < body >
60 < form id ="form1" runat ="server" >
61 < asp:DataGrid ID ="DataGrid1" runat ="server" OnItemCommand ="DataGrid1_ItemCommand" >
62 < Columns >
63 < asp:TemplateColumn HeaderText ="First Name" >
64 < ItemTemplate >
65 < asp:LinkButton ID ="LinkButton1" runat ="server" CommandName ="Select" Text ='<%#DataBinder.Eval(Container.DataItem,"fname")% > '>
66 </ asp:LinkButton >
67 </ ItemTemplate >
68 </ asp:TemplateColumn >
69 </ Columns >
70 </ asp:DataGrid >
71 < asp:Label ID ="Label1" runat ="server" ></ asp:Label >
72 </ form >
73 </ body >
74 </ html >
51行
2 if (e.CommandName == "Select")
3 Label1.Text = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
4}
5
只需在ItemCommand event的e.Item.ItemIndex就可以輕鬆的抓到RowIndex。
.NET 2.0 GridView
.NET 2.0就改用SqlDataSource和GridView了,LinkButtom一樣得放在TemplateField,但GridView沒有ItemCommand event,取而代之的是RowCommand event。
2
3 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
4
5 < script runat ="server" >
6 /**//*
7(C) OOMusou 2007 http://oomusou.cnblogs.com
8
9Filename : GridView_RowCommand_RowIndex.aspx
10Compiler : Visual Studio 2005 / C# 2.0 / ASP.NET 2.0
11Description : Demo how to get RowIndex in GridView's LinkButton
12Release : 06/26/2007 1.0
13*/
14 protected void Page_Load(object sender, EventArgs e) {
15 if (!IsPostBack)
16 GridView1_DataBind();
17 }
18
19 protected void GridView1_DataBind() {
20 SqlDataSource1.ConnectionString = @"Data Source=.\sqlexpress;Initial Catalog=pubs;Integrated Security=True";
21 SqlDataSource1.SelectCommand = "SELECT TOP 10 " +
22 "fname," +
23 "lname " +
24 "FROM employee";
25 GridView1.DataSourceID = SqlDataSource1.ID;
26 GridView1.DataKeyNames = new string[] { "lname" };
27 GridView1.AutoGenerateColumns = false;
28 }
29
30 protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) {
31 if (e.CommandName == "Select") {
32 int rowIndex = ((GridViewRow)((LinkButton)e.CommandSource).NamingContainer).RowIndex;
33 Label1.Text = GridView1.DataKeys[rowIndex].Value.ToString();
34 }
35 }
36 </ script >
37
38 < html xmlns ="http://www.w3.org/1999/xhtml" >
39 < head runat ="server" >
40 < title > Untitled Page </ title >
41 </ head >
42 < body >
43 < form id ="form1" runat ="server" >
44 < div >
45 < asp:GridView ID ="GridView1" runat ="server" OnRowCommand ="GridView1_RowCommand" >
46 < Columns >
47 < asp:TemplateField HeaderText ="First Name" >
48 < ItemTemplate >
49 < asp:LinkButton ID ="LinkButton1" runat ="server" CommandName ="Select" Text ='<%#Eval("fname")% > '> </ asp:LinkButton >
50 </ ItemTemplate >
51 </ asp:TemplateField >
52 </ Columns >
53 </ asp:GridView >
54 </ div >
55 < asp:Label ID ="Label1" runat ="server" ></ asp:Label >
56 < asp:SqlDataSource ID ="SqlDataSource1" runat ="server" ></ asp:SqlDataSource >
57 </ form >
58 </ body >
59 </ html >
最難理解的應該是32行
e.CommandSource傳的是按下去的LinkButton,不過由於傳回的是Object,就得自行轉成LinkButton,但由於我們想知道的是RowIndex,而LinkButton是包含在GridViewRow內,所以透過NamingContainer傳回目前的GridViewRow,但傳回的是Control,所以需在轉成GridViewRow後才能有RowIndex property。
Conclusion
GridView是DataGrid的繼承人,但不少寫法和DataGrid並不一樣,GridView很多地方比DataGrid更強更好用,但這個例子卻發現GridView比DataGrid麻煩些,或許我沒找到好最好的方法,若有人有更好的方式,歡迎指正,謝謝。