【问题标题】:Nested GridView Row Event Pandemonium嵌套的 GridView 行事件混乱
【发布时间】:2010-12-07 17:55:16
【问题描述】:

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

如果您将行事件属性显式添加到标记(例如 OnRowDeleted="gvInner_RowDeleted"),则行事件会为所有嵌套的网格视图触发,但它会为最后一行中的嵌套网格视图触发 两次外部gridview的

编辑: 我应该注意,我将 SqlDataSource 用于外部网格视图,因为它也是可编辑的。这在示例中并不清楚。

标记:

<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

任何人都可以重现此问题,您如何解决它?

【问题讨论】:

    标签: asp.net gridview


    【解决方案1】:

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

    这就是我将如何做你正在尝试的事情:

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

    标记

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

    【讨论】:

    • 感谢您的回答,但我这样做的原因超出了我的简化示例的范围。例如,内部和外部网格视图都利用了 SqlDataSource 的自动编辑/更新功能。如果我要使用转发器,我将不得不动态添加对 PostBacks 有问题的编辑控件。
    • 您仍然可以使用带有嵌套gridview 的sqldatasource,这将与repeater 控件的子数据项相关。我指出这一点的原因是因为 IMO 我认为您的外部 gridview 控件没有更新任何内容,只有嵌套的 gridview 正在处理更新。我的意思是,这就是你的代码看起来正在做的事情。
    • 如果您没有更改任何内容,则需要查看获取外层网格视图的行索引,然后获取嵌套网格视图的行索引并在该网格视图行上运行更新
    • 它将在行更新中。无需扩展之前已经完成的工作。请参考这个站点codeproject.com/KB/webforms/EditNestedGridView.aspx,它是在c#中的,但是你可以使用developerfusion.com/tools/convert/csharp-to-vb轻松转换它
    【解决方案2】:

    而答案是……

    从 RowDeleted 事件中删除句柄子句,并将 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 1970-01-01
      相关资源
      最近更新 更多