2010-12-07 53 views
0

我遇到了涉及嵌套的gridview控件和行事件的奇怪行爲。基本上嵌套的gridview行事件不會觸發,除非它位於外部網格的最後一行。嵌套的GridView行事件Pandemonium

如果你明確的行事件屬性添加到標記(如OnRowDeleted =「gvInner_RowDeleted」),然後所有嵌套GridView的行事件觸發但是它觸發兩次的外部GridView控件的最後一行中的嵌套的GridView

編輯:我應該注意到我使用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 

任何人都可以複製這一點,你怎麼解決呢?

回答

0

答案是......

取下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 
0

我不認爲你應該按照自己的方式去做。

這是我會怎麼做你嘗試什麼:

  1. 使用中繼器爲您的外部數據綁定控件,因爲它使更高效,它會知道你在努力實現與外部相同的效果gridview控件。
  2. 在你的代碼背後,檢索你的外部gridview(現在是一箇中繼器)的數據並加載到數據表中,並將其添加到數據集中,對內部gridview中的數據執行相同的操作。
  3. 然後使用DataSet.Relations.Add在數據集內創建數據表之間的關係.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() 
+0

感謝您的回答,但也有原因,我做這種方式這是我簡單的例子的範圍之外。例如,內部和外部網格視圖都利用了SqlDataSource的自動編輯/更新功能。如果我要使用中繼器,則必須動態添加用於編輯的控件,這些控件與PostBacks存在問題。 – plntxt 2010-12-07 18:31:54