嵌套的GridView行事件混乱

时间:2010-12-07 17:55:17

标签: asp.net gridview

我遇到了涉及嵌套gridview控件和行事件的奇怪行为。基本上,嵌套的gridview行事件不会触发,除非它位于外部网格的最后一行。

如果你明确地将行事件属性添加到标记(例如OnRowDeleted =“gvInner_RowDeleted”),那么行事件将触发所有嵌套的网格视图,但是它会为最后一行中的嵌套网格视图触发两次外网格视图

编辑:我应该注意到我使用SqlDataSource作为外部gridview,因为它也是可编辑的。这在示例中并不清楚。

标记:

<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"  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>

代码:

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

任何人都可以复制这个,你是如何解决它的?

2 个答案:

答案 0 :(得分:0)

我认为你不应该按照自己的方式做你正在做的事情。

以下是我如何做你正在尝试的事情:

  1. 使用转发器进行外部数据绑定控制,因为它可以更有效地渲染,并且它将与您尝试使用外部gridview控件实现相同的效果。
  2. 在您的代码中,检索外部gridview(现在是转发器)的数据并将其加载到数据表中并将其添加到数据集中,对内部gridview中的数据执行相同操作。
  3. 然后使用DataSet.Relations.Add
  4. 在数据集中创建数据表之间的关系
  5. 在数据集中的两个数据表之间创建关系后,您可以访问第二个数据表中的字段(列),这些字段将用于填充嵌套(内部)gridview控件的数据。
  6. 标记

    <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>
    

    背后的代码

    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()
    

答案 1 :(得分:0)

答案是......

从RowDeleted事件中删除handles子句,并将OnRowDeleted属性设置为gvInner_RowDeleted事件。

以下更新的代码。我只希望我的生命中最后4个小时回来。

标记:

<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>

代码:

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