Link to home
Start Free TrialLog in
Avatar of fakir420
fakir420

asked on

How to get reference to nested DataGrid

I have a nested datagrid for show details info. In the EditCommand prodedure I have the following code to bind the datagrid

Private Sub dgMaster_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgMaster.ItemDataBound
Dim drv As DataRowView = e.Item.DataItem
Dim dgChild As DataGrid = e.Item.Cells(9).FindControl("dgDetails")
dgChild.DataSource = drv.CreateChildView("ID")
dgChild.DataBind()
End Sub

I cannot get the reference to the "dgDetails" grid, dgChild is always nothing. I've also tried placing this code in the ItemDataBound event procedure with the same results. Datagrid code is listed below, any help is greatly appreciated.

<asp:datagrid id="dgMaster" style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 56px" runat="server"
Visible="False" AllowSorting="True" AllowPaging="True" PageSize="25" Width="576px" ShowFooter="True" AutoGenerateColumns="False" OnEditCommand="ShowDetails">
<Columns>
<asp:BoundColumn DataField="id" ReadOnly="True" HeaderText="ID"></asp:BoundColumn>
<asp:BoundColumn DataField="Part#" ReadOnly="True" HeaderText="Part #"></asp:BoundColumn>
<asp:BoundColumn DataField="SerialNum" ReadOnly="True" HeaderText="SerialNum"></asp:BoundColumn>
<asp:BoundColumn DataField="WorkOrder" ReadOnly="True" HeaderText="WorkOrder"></asp:BoundColumn>
<asp:BoundColumn DataField="Batch#" ReadOnly="True" HeaderText="Batch#"></asp:BoundColumn>
<asp:BoundColumn DataField="Description" ReadOnly="True" HeaderText="Description"></asp:BoundColumn>
<asp:BoundColumn DataField="Pass/Fail?" ReadOnly="True" HeaderText="Pass/Fail?"></asp:BoundColumn>
<asp:BoundColumn DataField="NumofFreqsTestedAt" ReadOnly="True" HeaderText="NumofGregTestedAt"></asp:BoundColumn>
<asp:BoundColumn DataField="NewStartTime" ReadOnly="True" HeaderText="NewStartTime"></asp:BoundColumn>
<asp:TemplateColumn>
<ItemTemplate>
<asp:LinkButton runat="server" Text="Show Details" CommandName="Edit" CausesValidation="false"></asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:DataGrid id="dgDetails" runat="server" ShowHeader="True">
<Columns>
<asp:BoundColumn DataField="field_name" HeaderText="Field Name"></asp:BoundColumn>
<asp:BoundColumn DataField="item_data" HeaderText="Data"></asp:BoundColumn>
</Columns>
</asp:DataGrid>
</EditItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:datagrid>

Avatar of Justin_W
Justin_W

See my comments in this PAQ:
https://www.experts-exchange.com/questions/21043976/footerTemplate-textbox-values.html

It contains the "FindControlsByID" utility method, which you can use to find _all_ controls with a specified non-unique id, no matter where they are in the page.  Then you can just look at the UniqueID to find out where your child grid really is.
Try:

Dim dgChild As DataGrid = e.Item.Cells(9).Controls(0)

You may want to put a break point at this line and then use the immediate pane to see how many controls the cell has:

? e.Item.Cells(9).Controls.Count

If it is more than one, check the id of each by its index and see what you get.

John
Avatar of fakir420

ASKER

I've tried checking the controls using the imediate pane, there are 3 literal controls?   I don't have any literals in the entire project which is why I am confused.
I've tried the FindControlsByID using the below code

Private Sub dgMaster_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgMaster.ItemDataBound
        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
            Dim drv As DataRowView = e.Item.DataItem
            Dim dgChild As DataGrid = CType(FindControlsByID(sender, "dgDetails")(0), DataGrid)
            dgChild.DataSource = drv.CreateChildView("ID")
            dgChild.DataBind()
        End If
    End Sub

I get 'Index was outside the bounds of the array' since the returned value is nothing.  I don't have this control referenced anywhere in the codebehind, only in html.  Is there some trick to finding it?
I know that literal controls in that situation are not unusual.  But I do not know exactly why they get added (by ASP.NET).  Do this for each of the controls in the cell in the immediate pane to see which index, if any, represnts the grid.

? e.Item.Cells(9).Controls(x).ID

where x = the index.  If the count is 4, then try the above with 0, 1, 2 and 3 and see what id each has (if any).

John
Use:
            Dim dgChild As DataGrid = CType(FindControlsByID(e.Item, "dgDetails")(0), DataGrid)
or:
            Dim dgChild As DataGrid = CType(FindControlsByID(e.Item.Cells(9), "dgDetails")(0), DataGrid)
instead of:
            Dim dgChild As DataGrid = CType(FindControlsByID(sender, "dgDetails")(0), DataGrid)
?e.Item.Cells(9).Controls(0).ID
Nothing
?e.Item.Cells(9).Controls(1).ID
Nothing
?e.Item.Cells(9).Controls(2).ID
Nothing

I've tried this over and over, even obtaining a reference to the dgMaster datagrid and trying to search it.  Also e.Item.DataItem is nothing, although I can get the text of other cells by e.Item.Cells(8).Text and e.Item.ItemIndex is the correct index value.  This is really starting to drive me nuts as I've tried everything I can think of 3 times with the same results - nothing.
Still not luck with the FindControlsByID method.  I tried both versions of the code posted above with the same results.  It's like the control doesn't exist...
ASKER CERTIFIED SOLUTION
Avatar of Justin_W
Justin_W

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I tried to code below - notice that it is now in the EditCommand - and still get the same thing.  Is there something else I need to do to load the EditItemTemplate?

Private Sub dgMaster_EditCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgMaster.EditCommand
        If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
            dgMaster.EditItemIndex = e.Item.ItemIndex
            Dim drv As DataRowView = e.Item.DataItem
            Dim dgChild As DataGrid = CType(FindControlsByID(e.Item, "dgDetails")(0), DataGrid)
            dgChild.DataSource = drv.CreateChildView("ID")
            dgChild.DataBind()
        End If

    End Sub
I finally got this working!  Justin_W is correct in that the EditItemTemplate was not loaded when I was trying to do reference the control in it.  After a little investigation, it seems that the EditItemTemplate will not be invoked until the next databind on the datagrid.  The combination of the two procedures below works!

Private Sub dgMaster_EditCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgMaster.EditCommand
        dgMaster.EditItemIndex = e.Item.ItemIndex
        BindData()  
End Sub

Private Sub dgMaster_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgMaster.ItemDataBound
        If dgMaster.EditItemIndex <> -1 And e.Item.ItemIndex = dgMaster.EditItemIndex Then
            'we are in edit mode and on the row being edited
            Dim drv As DataRowView = e.Item.DataItem
            Dim dgChild As DataGrid = e.Item.Cells(9).FindControl("dgDetails")
            dgChild.DataSource = drv.CreateChildView("ID")
            dgChild.DataBind()
        End If
End Sub

Thank you both for your comments, I am going to split the points, but Justin_W get more since the comment about the EditItemTemplate pointed me in the right direction.