How do I hide empty nested repeaters?

In an asp.net page, I have nested repeaters to render up to four levels of my sitemap.

Question: How can I tell nested relays not to show a node if the node has no children? More specifically, when the nested relay has no children, it displays as a pair of tags <ul></ul>

what I need to hide from the displayed list.

What works: The HTML and script provided here correctly renders web.sitemap as a pure unordered list, only with empty UL tags where node has no children.

What I have tried (unconvincing):

  • I looked into jQuery. While I found the correct jQuery command to remove empty pairs <ul>

    , the webresource is absolutely sure to overwrite jQuery commands. (Which also makes it impossible to use jQuery to remove the classes that put the rendered asp: menu). In other words, I have not yet found a way for jQuery to clean up something generated by the asp.net control.
  • I found forum posts, but they all seem to have repeated the same two-tier depth-repeater without removing the childless nodes.
  • I double checked the web.sitemap file and made sure I didn't have anything in the source that would facilitate this. No problem with the source.

Looking around I found a very promising post here: Hide child and parent repeater when child repeater is empty . Adapting it to VB.NET and adding a null detection if-then statement, I have:

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

      

Based on the comment, I also tried Sub Preender. He submitted a list of cards with the same empty UL tags. Using breakpoints didn't determine why it didn't work as desired.

This is the aspx code:

<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>

      

This is the rendered 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>    

      

  

So the sitemap that appears in the nested unordered list is correct, but still creates empty UL tags that should be removed on the server side.

+3


source to share


2 answers


For this system, this is what worked for me as a true server side answer.

In the script:

<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>

      

In the body (I also changed the asp: hyperlink tags to tags <a>

to clear all those hyperlinks in the rendered HTML):

<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>

      



And to prove to yourself this is a true server side solution, it's from the "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....

      

The places you saw are empty href tags because these specific nodes are more like folder containers, so the design is not a mistake.

Another plus for this approach is that there is only one subsystem that can be used by any of the repeaters, instead of using the chained approach as I previously tried.

+1


source


I think you are pretty much there. One of your problems is when you are trying to find Repeater3 in Repeater0 when it is actually in Repeater2. You need to walk down the repeater line correctly by finding the correct child ID. Here's an example of using the event OnPreRender

, although you can still make it work for OnItemDataBound

using similar logic.

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

      



In this case, every child repeater slips. If the child repeater has no items, hide the entire repeater. You can get an idea of ​​this code here. That said, you are probably better off recursively looping repeaters.

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

      

0


source







All Articles