Im working on a user control that shows available stores from an SQL table on a gridview for the user to select and fill up a textbox. Currently im able to databind everything correctly to the gridview and run actions with the select button inside each row. My current problem is that i can’t get to return the cell value into a variable when using "rows[index]". When i reach this i get an Index is out of range error even if my index value is correct while debugging.
For experiment purpose i gave the index a manual value of 0 and 1 on different iterations and i still get the error as if my gridview didn’t contain any rows.
My method to select the row is using a Gridview with an OnRowCommand triggered by a ButtonField.
Looking at some other similar questions and answers i found that most of the problems where around people getting negative values or not using DataKeyNames but this is not my case. I still can’t fix this error
My gridview code is this:
<asp:GridView ID="gvStore" runat="server" AutoGenerateColumns="False" Visible="false" DataKeyNames="Name" OnRowCommand="gvExecSelectSTR_RowCommand">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:ButtonField ButtonType="Link" Text="Select" CommandName="SelectStore"/>
</Columns>
</asp:GridView>
My button action
protected void gvExecSelectSTR_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "SelectStore")
{
int index = Convert.ToInt32(e.CommandArgument); //Up to this point i get correct row number for index
GridViewRow row = gvStore.Rows[index]; //This row triggers my error
IDStore.Text = row.Cells[0].Text;
}
}
Additionally, this is the method im using to databind everything to my GridView
private void GridViewStore()
{
try
{
DataTable StoreTable = new DataTable();
StoreTable.Columns.AddRange(new DataColumn[1]
{
new DataColumn("Name",typeof(string))
});
//Can't show internal SQL commands for this but here i read and load
the SQLscript that selects the table and load it into the reader variable "readerStore"//
if (readerStore.HasRows)
{
while (readerStore.Read())
{
StoreTable.Rows.Add(readerStore["Name"].ToString());
}
}
gvStore.DataSource = StoreTable;
gvStore.DataBind();
readerStore.Close();
}
catch (Exception ex)
{
OnErrorOccurred(new ErrorOccurredEventArgs("Grid View Bind Message" + ex.Message, ex));
}
}
Is there anything im setting up wrong?
2
Answers
Have you tried instead of
Doing this
why bother with row command? You really don’t need that event model, and in most cases, it just causes EXTRA pain.
And if you have a row PK id that you need on button click? Then use datakeys. Datakeys is VERY nice for several reasons.
For tops on the list, it always a HUGE security hole to expose data base PK’s to the client side. (the markup can be messed with, and thus the database ID you use now could be anything that was changed in the markup.
So, simple grid view say like this:
Note the data keys setting in above "ID" is our row PK id, and VERY nice is we do not have, display, show the PK row id in the markup at ANY time!!!
And code to fill then is this:
And we now have this:
Now, we need a click event for the button. For most buttons, you can just double click on the button to add/wire up a event. However, since the button is inside of the GV, then we can’t do that. But we can still add the event by markup.
So, in the markup type in onclick="" when you do this, intel-sense will pop up the option to create the event. Say like this:
(under the quotes, hit ctrl-space to pop that intel-sense dialog).
Ok, choose create new event.
Now, flip to code behind, there should be a simple click event for that button.
So, with this code:
Output:
So, with this simple setup:
If I have multiple buttons on the GV, then a get a nice simple SEPERATE click event and code stub. No messy row command (to then check some row command arugment).
I get the row index with ease.
I get the code behind NEVER exposed data base PK id (from datakeys)
I am free to get/grab any cell value from the current row.