2

All,

FYI: I am using VS2005, .net 2.0.

I have a GridView control that exists in the FormView EditItemTemplate. Unfortunately, the GridView misbehaves in that setup, its DataKeys collection is empty when the page posts back and the select command of the gridview fires.

Here is the sequence of events:

  1. User browses to the page
  2. User clicks 'edit' (FormView renders EditItemTemplate where the GridView is)
  3. The user clicks search which postbacks again and populates the GridView located in the EditItemTemplate (at this point the GridView has DataKeys)
  4. User selects item from GridView which raises row selected event
  5. On postback, the GridView RowCommand fires,- I check that the CommandName = "select" and run my code which throws exception because the DataKeys collection is empty at this point!

One more additional detail: The GridView lives in a user control that resides in the EditItemTemplate of the FormView.

NOTE:

I was able to resolve this problem when I move my GridView out of the EditItemTemplate of the FormView,- now DataKeys collection is NOT empty. Unfortunately, the GridView has to be in the EditItemTemplate for the user to select clients he searched for.

Any insight would be appreciated.

Event handling code:

protected void ctlSearchResults_RowCommand(object sender, GridViewCommandEventArgs e)
{
    // user has selected the client from the keyword search result list
    if (e.CommandName == "select")
    {
        GridView searchResultsGrid = (GridView)e.CommandSource;
        int selectedRowIndex = int.Parse((string)e.CommandArgument);
        int clientId = (int)searchResultsGrid.DataKeys[selectedRowIndex][Client.PROP_ENTITYID];
        // raise Selected event
        _OnSelected(new ClientSelectedEventArgs(clientId));
    }
}
ActiveX
  • 1,064
  • 1
  • 17
  • 37
  • Can you show your GridView RowCommand event code? – Josh Darnell Mar 07 '13 at 16:15
  • Yes, I have added the event handling code to problem description. The index out of range exception happens on the line where I try to assign clientId by referencing the DataKeys collection. DataKeys collection size at this point is zero. – ActiveX Mar 07 '13 at 16:20

3 Answers3

1

The reason that the DataKey collection is empty is because you are accessing the collection prior to data binding of the search results gridview. I find this guide useful when debugging order of processing problems.

FastGeek
  • 411
  • 2
  • 7
  • The GridView is already databound and receives its state from viewstate (or control state) on postback. This can observed by looking at the grid.Rows collection (every single row is there). Unfortunately, I cannot say the same thing for the grid.DataKeys collection, it is empty,- it should of been restored from the viewstate (or control state) on postback,- that was my understanding of how the gridview worked and I was accustomed to that because I have done this many times over. Unfortunately, in this case, I have deeper nesting and the Gridview is bound a bit later (on edit). – ActiveX Apr 04 '13 at 14:27
  • Just to add to my above comment: Interestingly enough, when I move the GridView from the Edit item template, it works! I haven't changed the sequence of events, they still happen in the exact order, just my gridview is outside the Edit item template. Clearly, something is really wrong and I don't think it has to do w/ my code. – ActiveX Apr 04 '13 at 14:31
  • Btw, the link you sent to the Page Life Cycle overview (which is great article),- believe it or not the diagram is printed out in colors and is hanging on my wall few inches away from me. – ActiveX Apr 04 '13 at 14:39
  • As a result of experiments I have found that the rows collection will be populated from the view state during the 'load' phase of the page life cycle, but for whatever reason the data key collection is empty until data binding has completed which seems to conclude in the 'PreRendering' phase. I have worked around this by setting a flag in my command event handler which is then used to trigger some process from the DataBound event. In your case you could assign the selected row index to a page variable, and then in the databound event check / use the variable to raise the selected event. – FastGeek Apr 04 '13 at 14:53
  • Thanks for your input. In my case, the solution is simpler: Instead of using DataKeys collection, I don't use it,- I just simply add a hidden field to store id of the record,- done. DataKeys collection does not play right w/ page life cycle. – ActiveX Apr 04 '13 at 19:43
  • Still useful after all these years... I'm trying to update the SelectedIndex of a gridview to follow the selected DataKey value after re-sorting (I'm in Mono ASP.NET which has not yet implemented GridView.EnablePersistedSelection, which does this automatically). My expectation was that I could find the DataKey value and update the SelectedIndex in the Sorted event handler, or in the PreRender event handler, but in both cases the SelectedIndex kept it's previous value. @FastGeek's results led me to try the DataBound handler and voila!, the SelectedIndex follows the re-sorted selected DataKey! – GISmatters May 29 '20 at 11:28
0

I believe you want to convert sender into the GridView as follows:

GridView searchResultsGrid = sender as GridView;
  • Either way, it accomplishes the same thing,- but that doesn't fix the problem with gridview.DataKeys.Count == 0. – ActiveX Mar 07 '13 at 20:13
  • Then you can:int clientId = (int)searchResultsGrid.DataKeys[searchResultsGrid.SelectedIndex ][Client.PROP_ENTITYID]; –  Mar 11 '13 at 20:27
  • Not if the collection is empty. – ActiveX Mar 12 '13 at 21:13
-1

Try this:

int selectedRowIndex = Convert.ToInt32(e.CommandArgument);
int clientId = Convert.ToInt32(this.yourGridView.DataKeys[selectedRowIndex]["yourDataKey"].Value);
Praveen Nambiar
  • 4,852
  • 1
  • 22
  • 31
  • 1
    All code that you see is valid. Again, the problem is that gridview.DataKeys.Count == 0 but it should be the # of records bound to the gridview. – ActiveX Mar 07 '13 at 20:14