Click GridView Find Selected Row

John Wesley Gordon picture John Wesley Gordon · Jan 7, 2014 · Viewed 48k times · Source

I'm trying to take a GridView and get back the data from the row that was clicked. I've tried the code below and when I click the row I get back the selected index but when I look at the actual rows in the GridView they show empty. Not sure what I am missing.

.ASP make my grid.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True" 
        CssClass="datatables" Width="100%" 
        DataSourceID="SqlDataSource1" 
        GridLines="None" ShowFooter="True" AllowSorting="True"  
        onrowcreated="GridView1_RowCreated" 
        onrowdatabound="GridView1_RowDataBound" ShowHeaderWhenEmpty="True" 
        onrowcommand="GridView1_RowCommand" 
        onselectedindexchanged="GridView1_SelectedIndexChanged">
        <HeaderStyle CssClass="hdrow" />
        <RowStyle CssClass="datarow" />
        <PagerStyle CssClass="cssPager" />
</asp:GridView>

On each row data bound I make sure that the click should set the selected index.

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.DataRow)
     {
        e.Row.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(GridView1, "Select$" + e.Row.RowIndex);
     }
 }

Then when the selected index changes by clicking this gets fired which I can put a breakpoint on the first line and I see the index of what I clicked on get stored in a. However when I get to the foreach it skips right past it because it shows GridView1 having a Count of 0 rows. In theory it should have a couple hundred rows and when the index matches it should grab the data in the 6th cell over and store it in string b. Why am I getting no rows on the click?

 protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
 {
            int a = GridView1.SelectedIndex

            foreach (GridViewRow row in GridView1.Rows)
            {
                if (row.RowIndex == a)
                {
                    b = row.Cells[6].Text;
                }
            }
 }

Here is my page load.

protected void Page_Load(object sender, EventArgs e)
{
      c = HttpContext.Current.Session["c"].ToString();
      SqlDataSource1.ConnectionString = //My secret
      string strSelect = "SELECT columnnames from tablenames where c in (@c)
      SqlDataSource1.SelectParameters.Clear();
      SqlDataSource1.SelectCommand = strSelect;
      SqlDataSource1.SelectParameters.Add("c", c);
       try
        {
            GridView1.DataBind();
        }
        catch (Exception e)
        {

        }
        GridView1.AutoGenerateColumns = true;
}

Answer

Josh Darnell picture Josh Darnell · Jan 7, 2014

Try just grabbing the row from the SelectedRow property:

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
    GridViewRow row = GridView1.SelectedRow;
    string b = row.Cells[6].Text;
}

It's my understanding that the Rows collection doesn't get repopulated on PostBacks when you're using those data source controls (like SqlDataSource).

You could probably use your existing code if you called .DataBind() on your GridView prior to trying to iterate through the Rows:

GridView1.DataSourceID="SqlDataSource1";
GridView1.DataBind();

But that seems a little hacky.


After seeing your Page_Load, I see that you need to wrap your databinding code in an if(!Page.IsPostBack) block. Databinding on every postback is interrupting the process of ASP.NET maintaining the state of your controls via the ViewState.