【问题标题】:How can I hide empty nested repeaters?如何隐藏空的嵌套中继器?
【发布时间】:2015-05-06 17:53:09
【问题描述】:

在一个 asp.net 页面中,我有嵌套的转发器来显示我的站点地图的四个级别。

问题: 如果节点没有子节点,我如何告诉嵌套中继器不显示节点?更具体地说,当嵌套中继器没有子节点时,它呈现为一对<ul></ul> 标签——这就是我需要从呈现列表中隐藏的内容。

工作原理:此处提供的 HTML 和脚本将 web.sitemap 正确地呈现为干净的无序列表,仅在节点没有子节点的情况下使用空 UL 标记。

到目前为止我尝试过的(不成功):

  • 我研究了 jQuery。虽然我找到了正确的 jQuery 命令来删除空的 <ul> 对,但 webresource 绝对确保覆盖 jQuery 命令。 (这也使我无法使用 jQuery 来删除乱扔渲染的 asp:menu 的类)。换句话说,我还没有找到让 jQuery 清理 asp.net 控件产生的东西的方法。
  • 我找到了论坛帖子,但它们似乎都重复了相同的两级深度中继器,而没有删除任何无子节点。
  • 我仔细检查了我的 web.sitemap 文件,并确保我的源文件中没有任何内容会导致此问题。源头没有问题。

环顾四周,我在这里发现了一个非常有前途的帖子: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 子。它提供了一个带有相同空 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 标签。

【问题讨论】:

  • 在您最近一次更新后,此时是否还有问题?
  • 是的。我距离发布下一个更新还有几分钟。这真的很奇怪:当我重建解决方案并查看呈现的 html 页面时,那里有空的 UL 标记。当我应用一个 jQuery 命令时,它具有删除标签的外观,以便我的 CSS 菜单正常工作,当我右键单击查看源代码时,空的 UL 标签仍然存在。
  • 我从不同的角度得出了一个答案。这是一个非常简单的子。现在,如果我可以简化主体中的嵌套中继器,那将是一个更大的胜利。
  • 太棒了 - 很高兴你能想出办法!

标签: jquery asp.net webforms


【解决方案1】:

对于这个系统,这对我来说是真正的服务器端答案。

在脚本中:

<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 标签更改为 &lt;a&gt; 标签以清理呈现的 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>

为了向自己证明这是一个真正的服务器端解决方案,这是来自“查看源代码”。

                        <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标签的地方是因为那些特定的节点更像是文件夹容器,所以这是设计而不是错误。

这种方法的另一个优点是只有一个 sub 可以被任何中继器使用,而不是像我之前尝试的那样必须使用链式方法。

【讨论】:

    【解决方案2】:

    我认为你几乎在那里。您的问题之一是您试图在Repeater0 中找到Repeater3,而它实际上位于Repeater2 中。您需要正确地沿着中继器行,找到正确的子 ID。这是一个使用 OnPreRender 事件的示例,尽管您仍然可以使用类似的逻辑让它为 OnItemDataBound 工作。

    <asp:Repeater runat="server" ID="Repeater0" DataSourceID="SiteMapDataSource1" OnPreRender="Repeater0_PreRender">
    

    在此事件中,挖掘每个子中继器。如果子中继器没有项目,则隐藏整个中继器。您应该能够从这里的代码中得到一个想法。但是,递归循环子中继器可能会更好。

    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
    

    【讨论】:

    • 谢谢。我现在正在测试那个代码块。我试图弄清楚“对于每个repeater1Item As RepeaterItem In rpt.Items”中的“rpt”是什么。您的意思是输入其他内容吗?
    • 抱歉,打错了。现在应该修好了。感谢您了解这一点。
    • 我试了两次,仍然看到空的
        标签。没有服务器错误,但呈现的 HTML 也没有变化 :( 你提到了递归。我喜欢这个概念,但迄今为止还没有找到嵌套中继器的示例。也许对“站点地图递归嵌套中继器”的字面搜索不是正确的搜索词?
    • 嗯...似乎对我和我的尝试有用。您是否设置了断点以确保它在应该将事物标记为隐藏时?
    • 我一直在使用“label1.text”方法,因为我们无法发出 vb 警报。 2 级的行为有点滑稽......重新检查代码是否有错别字。
    猜你喜欢
    • 2011-02-10
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    相关资源
    最近更新 更多