如何解决ASP.NET Webforms 嵌套 Gridview 单击父 gridview 行不显示子 gridview
我正在尝试构建一个带有嵌套 gridview 的 webforms 应用程序。问题是当我单击父网格视图中一行上的“+”时没有任何反应。见下文:
<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">×</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">×</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 时,它会尝试放入一列。
所以网格可能看起来像这样:
所以我有 + 符号来展开/显示嵌套的网格视图,我会得到这个:
(在此示例中展开显示已预订酒店的人)
你得到这个效果:
现在,您可以使用额外的锤子、锯子、钉子和锤子敲击这让网格视图展开并显示在行下方。
但是,GridView 不能很好地支持(如果有的话)多行行的能力。
然而,列表视图确实如此。因此,您可以保留嵌套的(子)gridview,并将其放入 ListView。
因此,列表视图将(应该/可以)看起来非常相似。像这样说:
但是,我可以让嵌套控件(gridview)占据整行,所以当我在列表视图中展开它时,我得到了这个:
如您所见,这看起来好多了。而且我不必与系统和布局作斗争 - 它的效果要好得多。
所以,这是我的 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 举报,一经查实,本站将立刻删除。