6

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;
}
John Wesley Gordon
  • 910
  • 2
  • 17
  • 39
  • The problem I had with `AutoGenerateSelectButton` is it actually puts the word Select next to everything. I just wanted a simple click on it, it does what it needs to response. Unfortunately there isn't an onClick event listed for GridView. – John Wesley Gordon Jan 07 '14 at 21:49
  • Yeah, sorry about that. I deleted my comment because I realized, from reading your code, that you wanted to have a click event on the whole row =) – Josh Darnell Jan 07 '14 at 21:52

1 Answers1

7

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.

Josh Darnell
  • 11,304
  • 9
  • 38
  • 66
  • When attempting to get the SelectedRow I get "'GridView1.SelectedRow' threw an exception of type 'System.ArgumentOutOfRangeException'" and "Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index" At the same time though GridView1.SelectedIndex has a value of 4 in it, which is what I would expect. – John Wesley Gordon Jan 07 '14 at 21:59
  • 1
    @JohnWesleyGordon are you sure the `6` is the proper column? The array is zero based, if you chose a column outside the range of columns it would throw that error. – crthompson Jan 07 '14 at 22:08
  • @paqogomez It is giving the error before that. It doesn't matter if I change it to a `row.Cells[0].Text;` – John Wesley Gordon Jan 07 '14 at 22:12
  • It seems like there must be something else going on in your page, then @John. Did you try the "hacky" solution I mentioned in my post (putting those two lines of code at the top of your original SelectedIndexChanged event)? – Josh Darnell Jan 07 '14 at 22:15
  • I just tried doing the `GridView1.DataBind()` again and that worked. I don't know if I like it though because if something changed between first databind and this new databind I won't be picking the right row. If the data was Bob, Frank, John and I select Frank, if I databind again and the data comes back as Bob, Carl, Frank, John wouldn't I get back that I selected Carl? – John Wesley Gordon Jan 08 '14 at 14:28
  • Hmmm, that's an interesting scenario, @John. I don't *think* that the databind operation will affect the SelectedValue, but you could always try it and see. I agree, though, that it is not optimal. Have you changed any of the defaults with regards to the ViewState? And are you doing any processing (related to the Grid, or to dynamic controls) in the early Page life cycle events (Load, Init, PreRender, PreInit, etc)? – Josh Darnell Jan 08 '14 at 14:43
  • No changes to ViewState. I am creating the query and databinding the first time for this GridView initially on Page_Load – John Wesley Gordon Jan 08 '14 at 14:49
  • @John Could you add your Page_Load code to the question? Are you doing all that in a `if(!Page.IsPostBack)` block (so it only happens on the initial page load)? Since you're using an `SqlDataSource`, I just assumed that you were not manually databinding at all in your codebehind. – Josh Darnell Jan 08 '14 at 14:54
  • @John feel free to pop in to [this chat room](http://chat.stackoverflow.com/rooms/44794/discussion-between-jadarnel27-and-john-wesley-gordon) if you want to talk in a more "real time" fashion. – Josh Darnell Jan 08 '14 at 14:56