如何隐藏空的嵌套中继器?
How can I hide empty nested repeaters?
在 asp.net 页面中,我嵌套了中继器以最多显示站点地图的四个级别。
问题: 如果节点没有children,我如何告诉嵌套中继器不显示节点? 更具体地说,当嵌套转发器没有 children 时,它呈现为一对 <ul></ul>
标记——这就是我需要从呈现列表中隐藏的内容。
什么有效: HTML 和此处显示的脚本将 web.sitemap 正确呈现为一个干净的无序列表,只有空的 UL 标签,其中一个节点没有 children.
到目前为止我尝试过的(未成功):
- 我调查了 jQuery。虽然我找到了正确的 jQuery 命令来删除空的
<ul>
对,但网络资源绝对确保覆盖 jQuery 命令。 (这也使我无法使用 jQuery 删除 类 渲染的 asp:menu)。换句话说,我还没有找到 jQuery 清理 asp.net 控件产生的东西的方法。
- 我找到了论坛 posts,但他们似乎都重复了相同的 two-level 深度转发器,而没有删除任何无子节点。
- 我 double-checked 我的 web.sitemap 文件并确保我在源代码中没有任何有助于此的内容。源头上没有问题。
环顾四周,我在这里发现了一个非常有前途的post:Hide child and parent repeater when child repeater is empty。使其适应 VB.NET 并添加空检测 if-then 语句,我有:
Protected Sub HideIfEmpty(sender As Object, e As RepeaterItemEventArgs) Handles Repeater0.ItemDataBound
If e.Item.ItemType = ListItemType.Item Then
If e.Item.FindControl("Repeater4") IsNot Nothing Then
If (DirectCast(e.Item.FindControl("Repeater3"), Repeater).Items.Count = 0) Then
e.Item.Visible = False
End If
End If
End If
End Sub
根据评论,我还尝试了 PreRender sub。它提供了一个带有相同空 UL 标签的站点地图列表。断点的使用未确定其未按预期工作的原因。
这是aspx代码:
<asp:SiteMapDataSource ID="siteMapDataSource1" runat="server" ShowStartingNode="false" />
<asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1">
<HeaderTemplate>
<ul>
<li>
<asp:HyperLink ID="HyperLink4" runat="server" NavigateUrl="~/index.aspx">Homepage</asp:HyperLink>
</li>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater ID="Repeater1" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>'>
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater ID="Repeater2" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>'>
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater ID="Repeater3" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnPreRender="HideIfEmpty">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
这是渲染出来的HTML:
<ul id="menu_Main" class="sm sm-blue">
<li>
<a id="Repeater0_HyperLink4" href="index.aspx">Homepage</a>
</li>
<li>
<a id="Repeater0_HyperLink1_0">Data Manager Documents</a>
<ul>
<li>
<a id="Repeater0_Repeater1_0_HyperLink2_0" href="/Data_Manager/Skill_Journal.aspx">Skill Journal</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_0_HyperLink2_1">Test Pages</a>
<ul>
<li>
<a id="Repeater0_Repeater1_0_Repeater2_1_HyperLink3_0" href="/Data_Manager/xslt_test.aspx">XSLT Test</a>
<ul>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<a id="Repeater0_HyperLink1_1">Incident Report</a>
<ul>
<li>
<a id="Repeater0_Repeater1_1_HyperLink2_0" href="http://wales:4885/IncidentReport/IncidentReport.aspx">Add/Edit/View</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_1_HyperLink2_1" href="http://wales:4885/IncidentReport/V1_History.aspx">Archive</a>
<ul>
</ul>
</li>
</ul>
</li>
<li>
<a id="Repeater0_HyperLink1_2" href="/Ordering_Database/Ordering_Database.aspx">Ordering Database</a>
<ul>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_0" href="/Ordering_Database/Reports.aspx">Reports</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_1" href="/Ordering_Database/Stats.aspx">Stats</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_2" href="/Ordering_Database/View_Items.aspx">View Items</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_3" href="/Ordering_Database/Manage_Items.aspx">Manage Items</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_4">Utility</a>
<ul>
</ul>
</li>
</ul>
</li>
总而言之,呈现为嵌套无序列表的站点地图是正确的,但仍然会产生空的 UL 标签,应在服务器端将其删除。
我想你已经差不多了。您的问题之一是您试图在 Repeater0 中找到 Repeater3,而实际上它在 Repeater2 中。您需要正确地沿着 Repeater 的路线向下,找到正确的子 ID。这是一个使用 OnPreRender
事件的示例,尽管您仍然可以使用类似的逻辑让它在 OnItemDataBound
上工作。
<asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1" OnPreRender="Repeater0_PreRender">
在此活动中,挖掘每个子转发器。如果子中继器没有物品,则隐藏整个中继器。你应该能够从这里的代码中得到一个想法。但是,递归循环子 Repeater 可能会更好。
Protected Sub Repeater0_PreRender(ByVal sender As Object, ByVal e As EventArgs)
Dim repeater0 As Repeater = sender
If repeater0.Items.Count = 0 Then
repeater0.Visible = False
Else
For Each repeater0Item As RepeaterItem In repeater0.Items
If repeater0Item.ItemType = ListItemType.Item Then
Dim repeater1 As Repeater = repeater0Item.FindControl("Repeater1")
If repeater1.Items.Count = 0 Then
repeater1.Visible = False
Else
For Each repeater1Item As RepeaterItem In repeater1.Items
If repeater1Item.ItemType = ListItemType.Item Then
Dim repeater2 As Repeater = repeater1Item.FindControl("Repeater2")
If repeater2.Items.Count = 0 Then
repeater2.Visible = False
Else
// so on and so forth
End If
End If
Next
End If
End If
Next
End If
End Sub
对于这个系统,这对我来说是真正的服务器端答案。
在脚本中:
<script>
Private Sub Hide_The_Orphans(ByVal sender As Object, ByVal e As RepeaterItemEventArgs)
Dim rpt As Repeater = CType(sender, Repeater)
If rpt IsNot Nothing Then
If rpt.Items.Count = 0 Then
rpt.Visible = False
Else
rpt.Visible = True
End If
End If
End Sub
</script>
在正文中(我还将 asp:hyperlink 标签更改为 <a>
标签以清理呈现的 HTML 中的所有超链接 ID):
<nav>
<asp:SiteMapDataSource ID="siteMapDataSource1" runat="server" ShowStartingNode="false" />
<asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1">
<HeaderTemplate>
<ul id="menu_Main" class="sm sm-blue">
<li>
<a href='<%# Page.ResolveClientUrl("~/index.aspx")%>'>Homepage</a>
</li>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
<asp:Repeater ID="Repeater1" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnItemDataBound="Hide_The_Orphans">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
<asp:Repeater ID="Repeater2" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnItemDataBound="Hide_The_Orphans">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
<asp:Repeater ID="Repeater3" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnItemDataBound="Hide_The_Orphans">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</nav>
为了向自己证明这是一个真正的服务器端解决方案,来自 "view source code."
<ul id="menu_Main" class="sm sm-blue">
<li>
<a href='index.aspx'>Homepage</a>
</li>
<li>
<a href=''>Data Manager Documents</a>
<ul>
<li>
<a href='/Data_Manager/Skill_Journal.aspx'>Skill Journal</a>
</li>
<li>
<a href=''>Test Pages</a>
<ul>
<li>
<a href='/Data_Manager/.aspx'>Sitemap test</a>
</li>
<li>
<a href='/Data_Manager/xslt_test.aspx'>XSLT Test</a>
</li>
</ul>
</li>
</ul>
</li>
etc....
你看到空 href 标签的地方是因为那些特定的节点更像是文件夹容器,所以这是设计而不是错误。
这种方法的另一个优点是只有一个子可以被任何中继器使用,而不是像我之前尝试的那样必须使用链式方法。
在 asp.net 页面中,我嵌套了中继器以最多显示站点地图的四个级别。
问题: 如果节点没有children,我如何告诉嵌套中继器不显示节点? 更具体地说,当嵌套转发器没有 children 时,它呈现为一对 <ul></ul>
标记——这就是我需要从呈现列表中隐藏的内容。
什么有效: HTML 和此处显示的脚本将 web.sitemap 正确呈现为一个干净的无序列表,只有空的 UL 标签,其中一个节点没有 children.
到目前为止我尝试过的(未成功):
- 我调查了 jQuery。虽然我找到了正确的 jQuery 命令来删除空的
<ul>
对,但网络资源绝对确保覆盖 jQuery 命令。 (这也使我无法使用 jQuery 删除 类 渲染的 asp:menu)。换句话说,我还没有找到 jQuery 清理 asp.net 控件产生的东西的方法。 - 我找到了论坛 posts,但他们似乎都重复了相同的 two-level 深度转发器,而没有删除任何无子节点。
- 我 double-checked 我的 web.sitemap 文件并确保我在源代码中没有任何有助于此的内容。源头上没有问题。
环顾四周,我在这里发现了一个非常有前途的post:Hide child and parent repeater when child repeater is empty。使其适应 VB.NET 并添加空检测 if-then 语句,我有:
Protected Sub HideIfEmpty(sender As Object, e As RepeaterItemEventArgs) Handles Repeater0.ItemDataBound
If e.Item.ItemType = ListItemType.Item Then
If e.Item.FindControl("Repeater4") IsNot Nothing Then
If (DirectCast(e.Item.FindControl("Repeater3"), Repeater).Items.Count = 0) Then
e.Item.Visible = False
End If
End If
End If
End Sub
根据评论,我还尝试了 PreRender sub。它提供了一个带有相同空 UL 标签的站点地图列表。断点的使用未确定其未按预期工作的原因。
这是aspx代码:
<asp:SiteMapDataSource ID="siteMapDataSource1" runat="server" ShowStartingNode="false" />
<asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1">
<HeaderTemplate>
<ul>
<li>
<asp:HyperLink ID="HyperLink4" runat="server" NavigateUrl="~/index.aspx">Homepage</asp:HyperLink>
</li>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater ID="Repeater1" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>'>
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater ID="Repeater2" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>'>
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
<asp:Repeater ID="Repeater3" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnPreRender="HideIfEmpty">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
这是渲染出来的HTML:
<ul id="menu_Main" class="sm sm-blue">
<li>
<a id="Repeater0_HyperLink4" href="index.aspx">Homepage</a>
</li>
<li>
<a id="Repeater0_HyperLink1_0">Data Manager Documents</a>
<ul>
<li>
<a id="Repeater0_Repeater1_0_HyperLink2_0" href="/Data_Manager/Skill_Journal.aspx">Skill Journal</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_0_HyperLink2_1">Test Pages</a>
<ul>
<li>
<a id="Repeater0_Repeater1_0_Repeater2_1_HyperLink3_0" href="/Data_Manager/xslt_test.aspx">XSLT Test</a>
<ul>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<a id="Repeater0_HyperLink1_1">Incident Report</a>
<ul>
<li>
<a id="Repeater0_Repeater1_1_HyperLink2_0" href="http://wales:4885/IncidentReport/IncidentReport.aspx">Add/Edit/View</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_1_HyperLink2_1" href="http://wales:4885/IncidentReport/V1_History.aspx">Archive</a>
<ul>
</ul>
</li>
</ul>
</li>
<li>
<a id="Repeater0_HyperLink1_2" href="/Ordering_Database/Ordering_Database.aspx">Ordering Database</a>
<ul>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_0" href="/Ordering_Database/Reports.aspx">Reports</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_1" href="/Ordering_Database/Stats.aspx">Stats</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_2" href="/Ordering_Database/View_Items.aspx">View Items</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_3" href="/Ordering_Database/Manage_Items.aspx">Manage Items</a>
<ul>
</ul>
</li>
<li>
<a id="Repeater0_Repeater1_2_HyperLink2_4">Utility</a>
<ul>
</ul>
</li>
</ul>
</li>
总而言之,呈现为嵌套无序列表的站点地图是正确的,但仍然会产生空的 UL 标签,应在服务器端将其删除。
我想你已经差不多了。您的问题之一是您试图在 Repeater0 中找到 Repeater3,而实际上它在 Repeater2 中。您需要正确地沿着 Repeater 的路线向下,找到正确的子 ID。这是一个使用 OnPreRender
事件的示例,尽管您仍然可以使用类似的逻辑让它在 OnItemDataBound
上工作。
<asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1" OnPreRender="Repeater0_PreRender">
在此活动中,挖掘每个子转发器。如果子中继器没有物品,则隐藏整个中继器。你应该能够从这里的代码中得到一个想法。但是,递归循环子 Repeater 可能会更好。
Protected Sub Repeater0_PreRender(ByVal sender As Object, ByVal e As EventArgs)
Dim repeater0 As Repeater = sender
If repeater0.Items.Count = 0 Then
repeater0.Visible = False
Else
For Each repeater0Item As RepeaterItem In repeater0.Items
If repeater0Item.ItemType = ListItemType.Item Then
Dim repeater1 As Repeater = repeater0Item.FindControl("Repeater1")
If repeater1.Items.Count = 0 Then
repeater1.Visible = False
Else
For Each repeater1Item As RepeaterItem In repeater1.Items
If repeater1Item.ItemType = ListItemType.Item Then
Dim repeater2 As Repeater = repeater1Item.FindControl("Repeater2")
If repeater2.Items.Count = 0 Then
repeater2.Visible = False
Else
// so on and so forth
End If
End If
Next
End If
End If
Next
End If
End Sub
对于这个系统,这对我来说是真正的服务器端答案。
在脚本中:
<script>
Private Sub Hide_The_Orphans(ByVal sender As Object, ByVal e As RepeaterItemEventArgs)
Dim rpt As Repeater = CType(sender, Repeater)
If rpt IsNot Nothing Then
If rpt.Items.Count = 0 Then
rpt.Visible = False
Else
rpt.Visible = True
End If
End If
End Sub
</script>
在正文中(我还将 asp:hyperlink 标签更改为 <a>
标签以清理呈现的 HTML 中的所有超链接 ID):
<nav>
<asp:SiteMapDataSource ID="siteMapDataSource1" runat="server" ShowStartingNode="false" />
<asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1">
<HeaderTemplate>
<ul id="menu_Main" class="sm sm-blue">
<li>
<a href='<%# Page.ResolveClientUrl("~/index.aspx")%>'>Homepage</a>
</li>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
<asp:Repeater ID="Repeater1" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnItemDataBound="Hide_The_Orphans">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
<asp:Repeater ID="Repeater2" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnItemDataBound="Hide_The_Orphans">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
<asp:Repeater ID="Repeater3" runat="server" DataSource='<%# DirectCast(Container.DataItem, SiteMapNode).ChildNodes%>' OnItemDataBound="Hide_The_Orphans">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href='<%# Eval("Url") %>'><%# Eval("Title") %></a>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</nav>
为了向自己证明这是一个真正的服务器端解决方案,来自 "view source code."
<ul id="menu_Main" class="sm sm-blue">
<li>
<a href='index.aspx'>Homepage</a>
</li>
<li>
<a href=''>Data Manager Documents</a>
<ul>
<li>
<a href='/Data_Manager/Skill_Journal.aspx'>Skill Journal</a>
</li>
<li>
<a href=''>Test Pages</a>
<ul>
<li>
<a href='/Data_Manager/.aspx'>Sitemap test</a>
</li>
<li>
<a href='/Data_Manager/xslt_test.aspx'>XSLT Test</a>
</li>
</ul>
</li>
</ul>
</li>
etc....
你看到空 href 标签的地方是因为那些特定的节点更像是文件夹容器,所以这是设计而不是错误。
这种方法的另一个优点是只有一个子可以被任何中继器使用,而不是像我之前尝试的那样必须使用链式方法。