微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASP.NET Webforms 嵌套 Gridview 单击父 gridview 行不显示子 gridview

如何解决ASP.NET Webforms 嵌套 Gridview 单击父 gridview 行不显示子 gridview

我正在尝试构建一个带有嵌套 gridview 的 webforms 应用程序。问题是当我单击父网格视图中一行上的“+”时没有任何反应。见下文:

enter image description here

我有以下代码

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Add Bill of Materials</h2>

    <script type="text/javascript">
        $(document).ready(function () {
            window.setTimeout(function () {
                $(".alert").fadeto(1500,0).slideUp(500,function () {
                    $(this).remove();
                });
            },3000);
        });

        function divexpandcollapse(divname) {
            var img = "img" + divname;
            if ($("#" + img).attr("src") == "../../Images/plus.png") {
                $("#" + img)
                    .closest("tr")
                    .after("<tr><td></td><td colspan = '100%' > " + $("#" + divname)
                        .html() + "</td></tr>")
                $("#" + img).attr("src","../../Images/minus.png");
            } else {
                $("#" + img).closest("tr").next().remove();
                $("#" + img).attr("src","../../Images/plus.png");
            }
        }
    </script>

    <div runat="server" visible="false" id="AlertDanger" class="alert alert-danger">
        <a href="#" class="close" data-dismiss="alert">&times;</a>BMDetails
        <strong>You must choose a date</strong>
    </div>

    <div runat="server" visible="false" id="AlertSuccess" class="alert alert-success">
        <a href="#" class="close" data-dismiss="alert">&times;</a>
        <strong>Purchase requisition saved successfully</strong>
    </div>
    <asp:Panel ID="BMDetails" runat="server">
        <div>
            <asp:UpdatePanel ID="UpdatePanelBM" runat="server">
                <ContentTemplate>
                    <fieldset class="form-horizontal">
                        <div class="row">
                            <div class="control-group col-sm-4">
                                <asp:Label runat="server" CssClass="col-sm-6 control-label" Style="text-align: left">Doc No.</asp:Label>
                                <div class="form-group col-sm-6">
                                    <asp:Label ID="lblDocNum" runat="server" CssClass="form-control" BackColor="#E6E6E6"></asp:Label>
                                </div>
                            </div>
                            <div class="control-group col-sm-8">
                                <asp:Label runat="server" CssClass="col-sm-6 control-label">Cust. PO No.</asp:Label>
                                <div class="form-group col-sm-6">
                                    <asp:TextBox ID="txtPurchaseDocNum" runat="server" AutopostBack="true" CssClass="form-control" OnTextChanged="txtPurchaseDocNum_TextChanged"></asp:TextBox>
                                    <ajaxToolkit:autocompleteextender
                                        ID="autocompleteextender1"
                                        runat="server"
                                        TargetControlID="txtPurchaseDocNum"
                                        ServicePath="../../Web_Service/PurchaSEOrders.asmx"
                                        ServiceMethod="GetPurchaSEOrders"
                                        MinimumPrefixLength="2"
                                        EnableCaching="true"
                                        CompletionSetCount="10"
                                        CompletionInterval="10"
                                        DelimiterCharacters=";,:"
                                        ShowOnlyCurrentWordInCompletionListItem="true">
                                    </ajaxToolkit:autocompleteextender>
                                    <asp:requiredFieldValidator runat="server" ControlTovalidate="txtPurchaseDocNum" display="Dynamic"
                                        CssClass="text-danger" ErrorMessage="The Cust. Purchase Order No field is required." />
                                </div>
                            </div>
                        </div>
                    </fieldset>
                    <asp:GridView ID="bMGridView"
                        runat="server"
                        AutoGenerateColumns="False"
                        AllowPaging="True"
                        AllowSorting="True"
                        ShowFooter="True"
                        OnPageIndexChanging="bMParentGrid_PageIndexChanging"
                        OnRowDataBound="bMParentGrid_RowDataBound"
                        OnRowCommand="bMParentGrid_RowCommand"
                        PagerStyle-CssClass="bs-pagination"
                        ShowHeaderWhenEmpty="True"
                        EmptyDataText="Select Customer PO number"
                        CssClass="table table-striped table-bordered table-hover table-condensed">
                        <Columns>                           
                            <asp:TemplateField ItemStyle-Width="20px">
                                <ItemTemplate>
                                    <a href="JavaScript:divexpandcollapse
                                    ('div<%# Eval("Item") %>');">
                                        <img alt="Details" id="imgdiv<%# Eval
                                        ("Item") %>"
                                            src="../../Images/plus.png" />
                                    </a>                                    
                                    <div id="div<%# Eval("Item") %>" style="display: none;">                                       
                                        <asp:GridView ID="bMChildGrid"
                                            runat="server"
                                            AutoGenerateColumns="False"
                                            AllowPaging="True"
                                            AllowSorting="True"
                                            ShowFooter="True"
                                            OnRowEditing="bMChildGrid_RowEditing"
                                            OnRowCancelingEdit="bMChildGrid_RowCancelingEdit"
                                            OnRowUpdating="bMChildGrid_RowUpdating"
                                            PagerStyle-CssClass="bs-pagination"
                                            ShowHeaderWhenEmpty="True"
                                            EmptyDataText="No Records Found"
                                            CssClass="table table-striped table-bordered table-hover table-condensed">
                                            <Columns>
                                                <asp:TemplateField ItemStyle-Width="30px" HeaderText="#">
                                                    <ItemTemplate>
                                                        <asp:Label ID="lblLineNum" Text='<%# Container.DataItemIndex + 1 %>' runat="server" />
                                                    </ItemTemplate>
                                                </asp:TemplateField>
                                                <asp:TemplateField ItemStyle-Width="500px" HeaderText="Item">
                                                    <ItemTemplate>
                                                        <asp:Label ID="lblItem" runat="server"
                                                            Text='<%# Bind("Item")%>'></asp:Label>
                                                    </ItemTemplate>
                                                    <EditItemTemplate>
                                                        <asp:TextBox ID="txtItem" runat="server" Width="500px" Text='<%# Bind("Item")%>'></asp:TextBox>
                                                        <ajaxToolkit:autocompleteextender
                                                            ID="autocompleteextender3"
                                                            runat="server"
                                                            TargetControlID="txtItem"
                                                            ServicePath="../../Web_Service/Items.asmx"
                                                            ServiceMethod="GetItems"
                                                            MinimumPrefixLength="2"
                                                            EnableCaching="true"
                                                            CompletionSetCount="10"
                                                            CompletionInterval="10"
                                                            DelimiterCharacters=";,:"
                                                            ShowOnlyCurrentWordInCompletionListItem="true">
                                                        </ajaxToolkit:autocompleteextender>
                                                        <asp:requiredFieldValidator runat="server" ControlTovalidate="txtItem" display="Dynamic" ValidationGroup="Edit"
                                                            CssClass="text-danger" ErrorMessage="The Item field is required." />
                                                    </EditItemTemplate>
                                                    <FooterTemplate>
                                                        <asp:TextBox ID="txtItem" runat="server" Width="500px"></asp:TextBox>
                                                        <ajaxToolkit:autocompleteextender
                                                            ID="autocompleteextender4"
                                                            runat="server"
                                                            TargetControlID="txtItem"
                                                            ServicePath="../../Web_Service/Items.asmx"
                                                            ServiceMethod="GetItems"
                                                            MinimumPrefixLength="2"
                                                            EnableCaching="true"
                                                            CompletionSetCount="10"
                                                            CompletionInterval="10"
                                                            DelimiterCharacters=";,:"
                                                            ShowOnlyCurrentWordInCompletionListItem="true">
                                                        </ajaxToolkit:autocompleteextender>
                                                        <asp:requiredFieldValidator runat="server" ControlTovalidate="txtItem" display="Dynamic" ValidationGroup="Insert"
                                                            CssClass="text-danger" InitialValue="-1" ErrorMessage="The Item field is required." />
                                                    </FooterTemplate>
                                                </asp:TemplateField>
                                                <asp:TemplateField ItemStyle-Width="120px" HeaderText="required Qty.">
                                                    <ItemTemplate>
                                                        <asp:Label ID="lblQuantity" runat="server"
                                                            Text='<%# Bind("Quantity")%>'></asp:Label>
                                                    </ItemTemplate>
                                                    <EditItemTemplate>
                                                        <asp:TextBox ID="txtQuantity" runat="server" Width="100px"
                                                            Text='<%# Bind("Quantity")%>'></asp:TextBox>
                                                        <asp:requiredFieldValidator runat="server" ControlTovalidate="txtQuantity" display="Dynamic" ValidationGroup="Edit"
                                                            CssClass="text-danger" ErrorMessage="The Quantity field is required." />
                                                        <asp:RegularExpressionValidator ControlTovalidate="txtQuantity" runat="server" CssClass="text-danger" display="Dynamic"
                                                            ErrorMessage="Only integers allowed." ValidationExpression="^(0|[1-9]\d*)$"
                                                            ValidationGroup="Edit"></asp:RegularExpressionValidator>
                                                    </EditItemTemplate>
                                                    <FooterTemplate>
                                                        <asp:TextBox ID="txtQuantity" runat="server" Width="100px"></asp:TextBox>
                                                        <asp:requiredFieldValidator runat="server" ControlTovalidate="txtQuantity" display="Dynamic" ValidationGroup="Insert"
                                                            CssClass="text-danger" ErrorMessage="The Quantity field is required." />
                                                        <asp:RegularExpressionValidator ControlTovalidate="txtQuantity" runat="server" CssClass="text-danger" display="Dynamic"
                                                            ErrorMessage="Only integers allowed." ValidationExpression="^(0|[1-9]\d*)$"
                                                            ValidationGroup="Insert"></asp:RegularExpressionValidator>
                                                    </FooterTemplate>
                                                </asp:TemplateField>
                                            </Columns>
                                        </asp:GridView>
                                    </div>
                                </ItemTemplate>
                            </asp:TemplateField>

                            <asp:TemplateField ItemStyle-Width="30px" HeaderText="#">
                                <ItemTemplate>
                                    <asp:Label ID="lblLineNum" Text='<%# Container.DataItemIndex + 1 %>' runat="server" />
                                </ItemTemplate>
                            </asp:TemplateField>

                            <asp:BoundField datafield="Item" HeaderText="Item" />
                            <asp:BoundField datafield="Quantity" HeaderText="Quantity" />

                        </Columns>
                    </asp:GridView>

                    <div class="form-group">
                        <div class="row">
                            <div class="col-sm-3">
                                <asp:Button runat="server" ID="InsertButton" OnClick="Insert" Text="Add" CssClass="btn btn-block btn-primary" />
                            </div>
                            <div class="col-sm-3">
                                <asp:Button runat="server" ID="CancelButton" OnClick="Cancel" Text="Cancel" CausesValidation="false" CssClass="btn btn-block btn-default" />
                            </div>
                        </div>
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
        </div>
    </asp:Panel>

</asp:Content>

这是我在背后的代码

protected void bMParentGrid_RowDataBound(object sender,GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DaTarow)
            {
                string item = Convert.ToString(DataBinder.Eval(e.Row.DataItem,"Item"));

                string selectedItem = item.Substring(0,item.IndexOf(' ')).Trim();

                GridView bMChildGrid = e.Row.FindControl("bMChildGrid") as GridView;

                // Create Data Table
                DataTable dt = new DataTable();
                dt.Columns.Add("lineNum",typeof(int));
                dt.Columns.Add("Item",typeof(string));
                dt.Columns.Add("Quantity",typeof(int));

                dt.Rows.Add(dt.NewRow());
                bMChildGrid.DataSource = dt;
                bMChildGrid.DataBind();               
            }
        }

我做错了什么?单击父网格行不会显示嵌入其中的子网格。

解决方法

嗯,我认为您不应该尝试在 gridview 中嵌套 gridview。

问题在于 GridView 不像列表视图那样支持“行跨度”。

当您展开该 GridView 时,它会尝试放入一列。

所以网格可能看起来像这样:

enter image description here

所以我有 + 符号来展开/显示嵌套的网格视图,我会得到这个:

(在此示例中展开显示已预订酒店的人)

你得到这个效果:

enter image description here

现在,您可以使用额外的锤子、锯子、钉子和锤子敲击这让网格视图展开并显示在行下方。

但是,GridView 不能很好地支持(如果有的话)多行行的能力。

然而,列表视图确实如此。因此,您可以保留嵌套的(子)gridview,并将其放入 ListView。

因此,列表视图将(应该/可以)看起来非常相似。像这样说:

enter image description here

但是,我可以让嵌套控件(gridview)占据整行,所以当我在列表视图中展开它时,我得到了这个:

enter image description here

如您所见,这看起来好多了。而且我不必与系统和布局作斗争 - 它的效果要好得多。

所以,这是我的 ListView 标记:

    <asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >

       <ItemTemplate>
          <tr style="">
            <td><asp:Button ID="cmdView" runat="server" Text="+" CommandName="Select" /></td>
            <td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
            <td><asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' /></td>
            <td><asp:Label ID="ProvinceLabel" runat="server" Text='<%# Eval("Province") %>' /></td>
            <td><asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' /></td>
          </tr>

          <tr>
            <td colspan="5">
               <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" 
                 DataKeyNames="ID" CssClass="table table-hover" style="display:none"  >
                    <Columns>
                        <asp:BoundField DataField="Firstname" HeaderText="Firstname" SortExpression="Firstname" />
                        <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                        <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
                    </Columns>
                </asp:GridView>

            </td>
           </tr>

           </ItemTemplate>

       <LayoutTemplate>
        <table id="itemPlaceholderContainer" runat="server" Class = "table table-hover" >
            <tr runat="server" style="">
                <th runat="server">View</th>
                <th runat="server">HotelName</th>
                <th runat="server">City</th>
                <th runat="server">Province</th>
                <th runat="server">Description</th>
            </tr>
            <tr id="itemPlaceholder" runat="server">
            </tr>
         </table>
       </LayoutTemplate>
    </asp:ListView>

如果您仔细观察,我们有第一个“tr”(表格行),即重复行。

然后我添加了额外的一行 - 给它一个 col span = 5(所以它占据一行

所以是驱动这个的代码。包括 + 按钮。如果你再次点击 +,我就会崩溃(隐藏网格视图)。

所以,代码看起来像这样:

Protected Sub Page_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then
        LoadGrid()
    End If

End Sub

Sub LoadGrid()

    Dim strSQL As String

    strSQL = "SELECT * FROM tblHotels ORDER BY HotelName"

    Using cmdSQL As New SqlCommand(strSQL,New SqlConnection(My.Settings.TEST4))

        cmdSQL.Connection.Open()

        ListView1.DataSource = cmdSQL.ExecuteReader
        ListView1.DataBind()

    End Using

End Sub

这样就显示了我们的网格。当然,我们有“+”按钮,它只是加载给定行的网格,然后将样式(显示)变为正常。

代码是这样的:

Protected Sub ListView1_SelectedIndexChanged(sender As Object,e As EventArgs) Handles ListView1.SelectedIndexChanged

    Dim gVR As ListViewDataItem = ListView1.Items(ListView1.SelectedIndex)
    Dim gChild As GridView = gVR.FindControl("GridView2")   ' pluck out the grid for this row

    If gChild.Style("display") = "normal" Then
        ' if grid is already display,then hide it,and exit
        gChild.Style("display") = "none"
        Exit Sub
    End If

    gChild.Style("display") = "normal"
    Dim HotelPK As String = ListView1.DataKeys(gVR.DataItemIndex).Item("ID")

    Dim strSQL As String
    strSQL = "SELECT * from People where hotel_id = " & HotelPK

    Using cmdSQL As New SqlCommand(strSQL,New SqlConnection(My.Settings.TEST4))

        cmdSQL.Connection.Open()
        gChild.DataSource = cmdSQL.ExecuteReader
        gChild.DataBind()

    End Using

End Sub

Protected Sub ListView1_SelectedIndexChanging(sender As Object,e As ListViewSelectEventArgs) Handles ListView1.SelectedIndexChanging

End Sub

代码不多,我们可以深入查看,甚至可以切换显示、隐藏。

我真的建议您将其移至父级的 ListView。子项可以保留为 gridView,或其他任何内容。

并注意 listView 有多好 - 您只需在常规控件中拖放即可 - 您不需要像使用 GridView 那样一遍又一遍地使用模板化列。

对于大多数简单的网格——或者没有太多自定义的网格,GridView 非常好。

但是,当您有很多自定义控件并且需要很多花哨的东西和更多的灵活性时?然后你必须拿出大枪并开始使用 ListView。

listview 开始时往往是“一点点”更多的标记,但由于它具有近乎无限的灵活性,那么对于复杂的酷炫和惊人的网格控件,listView 更能应对挑战,并且在布局上有更多的灵活性。

ListView 的一大特点是能够为一个数据记录设置多行布局——这对于 GridView 来说往往非常困难。 ListView 允许您为每个记录提供“更多”然后一行详细信息,并具有有价值的 colspan(甚至还有 rowspan)。

所以对于只有一行控件,GridView 很好,但是一旦你想要更多的数据列,那么 ListView 就是这里的票。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。