We are using the latest service pack of the Q3 2008 RadGrid. My grid has 2 levels of hierarchy, the first level is just a list of people's names and the second level is detailed information about their order.
Below is the NeedDataSource function. DataSourcePeople is a datatable stored in viewstate.
Private Sub grdPerson_NeedDataSource(ByVal source As Object, ByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles grdPerson.NeedDataSource |
grdPerson.DataSource = DataSourcePeople |
End Sub |
When the grid runs it's PreRender event, it runs the following code. This is used to look in the DataSource (another datatable with their order information) to see if the row has been previously selected so that we can reselect the items after paging, sorting, etc.
Private Sub grdPerson_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles grdPerson.PreRender |
For Each item As Telerik.Web.UI.GridItem In grdPerson.MasterTableView.ItemsHierarchy |
If item.OwnerTableView.Name = "Detail" Then |
If DataSource.Select("ResourceID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("ResourceID") & "' AND PersonID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("PersonID") & "'").Length > 0 Then |
If DataSource.Select("ResourceID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("ResourceID") & "' AND PersonID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("PersonID") & "'")(0)("Selected") = True Then |
item.Selected = True |
Else |
item.Selected = False |
End If |
End If |
End If |
Next |
End Sub |
When a user expands a person to see their orders the following code is run in the DetailTableDataBind event. The ExpandPerson function simply finds all of the person's orders and adds them to the DataSource data table so that it can be bound.
Dim dataitem As Telerik.Web.UI.GridDataItem = CType(e.DetailTableView.ParentItem, Telerik.Web.UI.GridDataItem) |
If DataSource.Select("PersonID = '" & dataitem.GetDataKeyValue("PersonID") & "'").Length = 0 Then |
ExpandPerson(dataitem.GetDataKeyValue("PersonID")) |
End If |
e.DetailTableView.DataSource = DataSource.Select("PersonID = '" & dataitem.GetDataKeyValue("PersonID") & "'", "Course ASC") |
Finally, we have our event (the ItemCommand) to track what was changed in the detail table so that we can reselect them when the user expands the person again (assuming they do expand the person after collapsing them). This appears to be where the trouble begins.
Private Sub grdPerson_ItemCommand(ByVal source As Object, ByVal e As Telerik.Web.UI.GridCommandEventArgs) Handles grdPerson.ItemCommand |
If e.CommandName = "ExpandCollapse" Then |
For Each item As Telerik.Web.UI.GridItem In grdPerson.MasterTableView.ItemsHierarchy |
If item.Selected Then |
If DataSource.Select("ResourceID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("ResourceID") & "' AND PersonID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("PersonID") & "'").Length > 0 Then |
Dim dr As DataRow = DataSource.Select("ResourceID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("ResourceID") & "' AND PersonID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("PersonID") & "'")(0) |
dr("Selected") = True |
dr("Hours") = CType(item.FindControl("txtHours"), TextBox).Text |
dr("Minutes") = CType(item.FindControl("txtMinutes"), TextBox).Text |
dr("Score") = CType(item.FindControl("txtScore"), TextBox).Text |
dr("CompletionDate") = CType(item.FindControl("txtCompletionDate"), TextBox).Text |
dr("CompletionDeadline") = CType(item.FindControl("txtCompletionDeadline"), TextBox).Text |
End If |
Else |
If DataSource.Select("ResourceID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("ResourceID") & "' AND PersonID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("PersonID") & "'").Length > 0 Then |
DataSource.Select("ResourceID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("ResourceID") & "' AND PersonID = '" & item.OwnerTableView.DataKeyValues(item.ItemIndex).Item("PersonID") & "'")(0)("Selected") = False |
End If |
End If |
Next |
End If |
End Sub |
The initial NeedDataSource to populate the people's names works just fine. When a user clicks on the button to expand the grid it runs the events in the following order:
- ItemCommand (ExpandCollapse)
- NeedDataSource
- DetailTableDataBind
- PreRender
When a user collapses the person after expanding them it runs the following events:
- ItemCommand (ExpandCollapse)
- PreRender
The problem occurs when I select something before collapsing. This causes it to run the following events:
- ItemCommand (ExpandCollapse, it updates the DataSource data table with the correct values)
- PreRender
- NeedDataSource
- DetailTableDataBind
Their are few problems with this. First, it doesn't collapse as it should. Second, even though it doesn't collapse it loses it's selection (since the PreRender event doesn't fire to reselect it). Other columns (for example Score, Hours, etc.) show with the values entered. Any idea why it would decide to run the NeedDataSource and DetailTableDataBind after updating the data. My first inclination was that it was doing this because it detected that it's data sources have changed and therefore it needed to rebind, however, just because it rebinds doesn't mean that it shouldn't still collapse as it's supposed to.
Any help would be greatly appreciated. The end goal is that I can have a grid that I can expand and collapse correctly and it would keep the items selected inside of the detail table when I would expand to view it again.
Thanks,
Adam