开发者

Nested GridView Row Event Pandemonium

开发者 https://www.devze.com 2023-01-29 21:58 出处:网络
I have come across odd behavior involving nested gridview controls and row events.Basically the nested gridview row event will not fire unless it is in the last row of the outer grid.

I have come across odd behavior involving nested gridview controls and row events. Basically the nested gridview row event will not fire unless it is in the last row of the outer grid.

If you explicitly add the row event property to the markup (e.g. OnRowDeleted="gvInner_RowDeleted") then the row event fires for all nested gridviews however it fires twice for the nested gridview in the last row of the outer gridview

EDIT: I should note that I am using the SqlDataSource for the outer gridview as it is also editable. This isn't clear in the example.

Markup:

<asp:Grid开发者_如何学GoView ID="gvOuter" DataSourceID="sdsOuter" runat="server" OnRowDatabound="DynamicControlAdder" AutoGenerateColumns="false">
    <Columns>
        <asp:BoundField DataField="Id" ReadOnly="true" />
        <asp:TemplateField>
            <ItemTemplate>        

                        <asp:UpdatePanel ID="upInner" runat="server" UpdateMode="Conditional">
                            <ContentTemplate>                                
                                <asp:GridView ID="gvInner" DataSourceId="sdsInner" runat="server" DataKeyNames="Id"  AutoGenerateColumns="false">
                                    <Columns>
                                        <asp:CommandField ShowDeleteButton="true" />
                                        <asp:BoundField DataField="Id" />                                            
                                    </Columns>
                                </asp:GridView>
                                <asp:SqlDataSource ID="sdsInner" runat="server" 
                                    ProviderName="<%$ ConnectionStrings:YourString.ProviderName %>" 
                                    ConnectionString="<%$ ConnectionStrings:YourString %>"
                                    SelectCommand="SELECT * FROM tblInner WHERE OuterTableKey = @OuterTableKey"
                                    DeleteCommand="DELETE FROM tblInner WHERE Id = @Id">
                                    <SelectParameters>
                                        <asp:Parameter Name="OuterTableKey" DefaultValue="0" Type="Int32" />
                                    </SelectParameters>
                                    <DeleteParameters>
                                        <asp:Parameter Name="Id" DefaultValue="0" Type="Int32" />                                            
                                    </DeleteParameters>                                        
                                </asp:SqlDataSource>                                                 
                            </ContentTemplate>                
                        </asp:UpdatePanel>    

            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdsOuter" runat="server"
   ProviderName="<%$ ConnectionStrings:YourString.ProviderName %>" 
   ConnectionString="<%$ ConnectionStrings:YourString %>"
   SelectCommand="SELECT * FROM tblOuter">                                        
</asp:SqlDataSource>

Code:

Partial Class Testing
Inherits System.Web.UI.UserControl

Protected Sub DynamicControlAdder(ByVal sender As Object, ByVal e As GridViewRowEventArgs)

    If e.Row.RowType <> DataControlRowType.DataRow Then
        Exit Sub
    End If

    Dim s As SqlDataSource = CType(e.Row.FindControl("sdsInner"), SqlDataSource)
    s.SelectParameters("OuterTableKey").DefaultValue = e.Row.DataItem("Id").ToString()

End Sub

Protected Sub gvInner_RowDeleted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeletedEventArgs) Handles gvInner.RowDeleted
    //'This never fires unless it is the last row in the outer gridview
    //'also, if this event is declared in the OnRowDeleted property of the inner gridview, this event fires twice if it is in the last row of the outer grid
    Dim strFoo As String = "Foo"
End Sub
End Class

Can anybody reproduce this, and how do you work around it?


I don't think you should doing what you're doing the way you're doing it.

Here's how I would do what you're attempting:

  1. Use a repeater for your outer databound control as it renders more efficiently and it will have the same effect you're trying to achieve with the outer gridview control.
  2. In your code behind, retrieve your data for your outer gridview (which is now a repeater) and load it into a datatable and add it to a dataset, do the same for data in the inner gridview.
  3. Then create a relation between the datatables within the dataset using DataSet.Relations.Add
  4. Once you create the relationship between both datatables in the dataset, you can access the fields (columns) in your second datatable which will be used to populate the data for the nested (inner) gridview control.

Markup

<asp:Repeater ID="rpt1" runat="server">
    <ItemTemplate>
        <asp:GridView ID="gv1" runat="server" DataSource='<%# Container.DataItem.Row.GetChildRows("relation1") %>' GridLines="None" AutoGenerateColumns="false">
            <columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:TextBox ID="txt1" runat="server" Text='<%# Container.DataItem("<column>") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
            </columns>
        </asp:GridView>
    </ItemTemplate>
</asp:Repeater>

Code Behind

Dim ds As New DataSet
Dim dt1 As DataTable = obj.<method> 'Outer data
Dim dt2 As DataTable = obj.<method> 'Inner data

ds.Tables.Add(dt1)
ds.Tables.Add(dt2)

ds.Relations.Add("relation1", ds.Tables(0).Columns("<unique identifier column name>"), ds.Tables(1).Columns("<unique id column name>"), False)

rpt1.DataSource = dt1
rpt1.DataBind()


And the answer is......

Remove the handles clause from the RowDeleted Event and set the OnRowDeleted Property to the gvInner_RowDeleted event.

Updated code below. I just wish i had the last 4 hours of my life back.

Markup:

<asp:GridView ID="gvOuter" DataSourceID="sdsOuter" runat="server" OnRowDatabound="DynamicControlAdder" AutoGenerateColumns="false">
    <Columns>
        <asp:BoundField DataField="Id" ReadOnly="true" />
        <asp:TemplateField>
            <ItemTemplate>        

                        <asp:UpdatePanel ID="upInner" runat="server" UpdateMode="Conditional">
                            <ContentTemplate>                                
                                <asp:GridView ID="gvInner" DataSourceId="sdsInner" runat="server" DataKeyNames="Id" OnRowDeleted="gvInner_RowDeleted"  AutoGenerateColumns="false">
                                    <Columns>
                                        <asp:CommandField ShowDeleteButton="true" />
                                        <asp:BoundField DataField="Id" />                                            
                                    </Columns>
                                </asp:GridView>
                                <asp:SqlDataSource ID="sdsInner" runat="server" 
                                    ProviderName="<%$ ConnectionStrings:YourString.ProviderName %>" 
                                    ConnectionString="<%$ ConnectionStrings:YourString %>"
                                    SelectCommand="SELECT * FROM tblInner WHERE OuterTableKey = @OuterTableKey"
                                    DeleteCommand="DELETE FROM tblInner WHERE Id = @Id">
                                    <SelectParameters>
                                        <asp:Parameter Name="OuterTableKey" DefaultValue="0" Type="Int32" />
                                    </SelectParameters>
                                    <DeleteParameters>
                                        <asp:Parameter Name="Id" DefaultValue="0" Type="Int32" />                                            
                                    </DeleteParameters>                                        
                                </asp:SqlDataSource>                                                 
                            </ContentTemplate>                
                        </asp:UpdatePanel>    

            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdsOuter" runat="server"
   ProviderName="<%$ ConnectionStrings:YourString.ProviderName %>" 
   ConnectionString="<%$ ConnectionStrings:YourString %>"
   SelectCommand="SELECT * FROM tblOuter">                                        
</asp:SqlDataSource>

Code:

Partial Class Testing
Inherits System.Web.UI.UserControl

Protected Sub DynamicControlAdder(ByVal sender As Object, ByVal e As GridViewRowEventArgs)

    If e.Row.RowType <> DataControlRowType.DataRow Then
        Exit Sub
    End If

    Dim s As SqlDataSource = CType(e.Row.FindControl("sdsInner"), SqlDataSource)
    s.SelectParameters("OuterTableKey").DefaultValue = e.Row.DataItem("Id").ToString()

End Sub

Protected Sub gvInner_RowDeleted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeletedEventArgs) 
    //' Now we're talking
    Dim strFoo As String = "Foo"
End Sub
End Class
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号