【问题标题】:How can I turn the output of asp:SiteMapPath into a list?如何将 asp:SiteMapPath 的输出转换为列表?
【发布时间】:2011-11-27 10:09:15
【问题描述】:

我对 .NET 和 VB.NET 都非常不熟悉,并且不知道该怎么做。假设我有这样的代码:

<div class="breadcrumb">
    <asp:SiteMapPath ID="SiteMapPath1" runat="server"></asp:SiteMapPath>
</div>

它输出一堆&lt;span&gt;s,以&gt;作为分隔符,如下所示:

<div class="breadcrumb">
  <span id="ctl00_SiteMapPath1">
    <a href="#ctl00_SiteMapPath1_SkipLink">
      <img alt="Skip Navigation Links" height="0" width="0" src="/Bonfield/WebResource.axd?d=PEpmmIw6qvhaEC3hEwXGjgvJKlzc3DOMu_e-zW-n6pfl6YR-iYjwmlvrYPb689EslKxysA7aoh_x_ALjLs5QXiz7NG41&amp;t=634245478914809245" style="border-width:0px;" />
    </a>
    <span>
      <a href="/Bonfield/Default.aspx">Home</a>
    </span>
    <span> &#187; </span>
    <span>Showcase</span><a id="ctl00_SiteMapPath1_SkipLink"></a></span>
</div>

我怎样才能把它变成这样的列表:

<ul>
  <li>Home</li>
  <li>Showcase</li>
</ul>

【问题讨论】:

    标签: .net vb.net


    【解决方案1】:

    虽然有点涉及,但这是一个实际删除跨度并呈现干净列表的解决方案。

    首先,通过修改SiteMapPath 去除那些多余的跨度。我派生了一个类NakedSiteMapPath 来执行此操作。如果需要,它仍然允许在模板中使用显式跨度:

    /// <summary>
    ///     A SiteMapPath, that does not render span elements.
    /// </summary>
    /// <remarks>
    ///     To still allow explizit spans inside the node templates, immediately prefix the opening and closing span elements
    ///     with the literal
    ///     prefix "<!--KEEP NEXT SPAN-->" (without the double quotes)
    ///     Example:
    ///     <code>
    ///     <PathSeparatorTemplate><!--KEEP NEXT SPAN--><span class="icon icon--greater"><!--KEEP NEXT SPAN--></span>
    ///         </PathSeparatorTemplate>
    /// </code>
    ///     Those spans (opening and closing) will be kept, but the prefix removed in the rendered output.
    /// </remarks>
    /// <devdoc>
    ///     The MSDN doc has a nice example about a customized breadcrumb with a dropdown menu here:
    ///     https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.sitemappath%28v=vs.110%29.aspx
    /// </devdoc>
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    [ToolboxData("<{0}:NakedSiteMapPath runat=server></{0}:NakedSiteMapPath>")]
    public class NakedSiteMapPath : SiteMapPath {
        /// <summary>
        ///     Outputs server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter" /> object and stores
        ///     tracing information about the control if tracing is enabled.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter" /> object that receives the control content.</param>
        public override void RenderControl(HtmlTextWriter writer) {
            //Render to a local string, then remove all unnecessary spans
            StringBuilder myStringBuilder = new StringBuilder();
            TextWriter myTextWriter = new StringWriter(myStringBuilder);
            HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);
            base.RenderControl(myWriter);
    
            string html = myStringBuilder.ToString();
    
            //Remove all spans, except those opening and closing spans wich have been marked with the literal comment "<!--KEEP NEXT SPAN-->"
            const string matchOpenExceptSkipPrefix = @"(?<!\<\!--KEEP NEXT SPAN--\>)<span>";
            const string matchCloseExceptSkipPrefix = @"(?<!\<\!--KEEP NEXT SPAN--\>)</span>";
            html = Regex.Replace(html, matchOpenExceptSkipPrefix, String.Empty);
            html = Regex.Replace(html, matchCloseExceptSkipPrefix, String.Empty);
            html = html.Replace(@"<!--KEEP NEXT SPAN-->", String.Empty);
    
            //finally, write the naked html out.
            writer.Write(html);
        }
    }
    

    这样,跨度就消失了。要拥有自定义链接,如 li 元素,您将需要使用模板,正如其他人已经提出的那样。这是带有 NakedSiteMapPath 的示例 ASPX 页面部分:

    <ol class="breadcrumb" role="navigation" aria-labelledby="pagebreadcrumbs">
        <my:NakedSiteMapPath runat="server"
            PathDirection="RootToCurrent"
            RenderCurrentNodeAsLink="False">
            <PathSeparatorTemplate><!--KEEP NEXT SPAN--><span class="icon icon--greater"><!--KEEP NEXT SPAN--></span></PathSeparatorTemplate>
            <CurrentNodeTemplate>
                <li class="active" aria-selected="true">
                    <asp:Literal
                        Text='<%# Eval("Title") %>'
                        runat="server" />
                </li>
            </CurrentNodeTemplate>
            <NodeTemplate>
                <li>
                    <asp:HyperLink
                        ID="lnkPage"
                        Text='<%# Eval("Title") %>'
                        NavigateUrl='<%# Eval("Url") %>'
                        ToolTip='<%# Eval("Description") %>'
                        runat="server" />
                </li>
            </NodeTemplate>
        </my:NakedSiteMapPath>
    </ol>
    

    【讨论】:

    • 来自 ASP 菜鸟的问题:如何注册 my:NakedSiteMapPath 以便您可以在 .aspx 中使用它?
    【解决方案2】:

    您现在可能已经解决了这个问题,但是您可以使用此函数循环遍历站点地图根节点中的所有项目及其后代,并构建一个嵌套列表。

    如果你只对顶层感兴趣,你可以删除If item.HasChildNodes Then sb.Append(ListChildNodes(item))

     Public Function SiteMap() As String
            Return ListChildNodes(System.Web.SiteMap.RootNode)
        End Function
    
        Private Function ListChildNodes(ByVal node As System.Web.SiteMapNode) As String
            Dim sb As New System.Text.StringBuilder
    
            sb.Append("<ul>")
            For Each item As SiteMapNode In node.ChildNodes
                sb.Append(String.Concat("<li><a href=""", item.Url, """>", item.Title, "</a></li>"))
                If item.HasChildNodes Then sb.Append(ListChildNodes(item))
            Next
            sb.Append("</ul>")
    
            Return sb.ToString
        End Function
    

    对于那些想要 C# 版本的人:

    public string SiteMap()
            {
                return ListChildNodes(System.Web.SiteMap.RootNode);
            }
            private string ListChildNodes(System.Web.SiteMapNode node)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
    
                sb.Append("<ul>");
                foreach (SiteMapNode item in node.ChildNodes)
                {
                    sb.Append(string.Concat("<li><a href=\"", item.Url, "\">", item.Title, "</a></li>"));
                    if (item.HasChildNodes)
                        sb.Append(ListChildNodes(item));
                }
                sb.Append("</ul>");
    
                return sb.ToString();
            }
    

    然后在您的代码中,您可以调用将字符串输出到页面。

    <h1>Site Map</h1>
        <%=SiteMap()%>
    </div>
    

    【讨论】:

    • 这很好,除了节点中的所有内容都显示出来了:/
    【解决方案3】:

    最好的选择是将 SiteMapPath 转换为使用模板。

    &lt;NodeTemplate&gt; 中,您可以使用您需要的格式放置&lt;li&gt; 元素。 在&lt;PathSeparatorTemplate&gt; 中可以放置分隔符。

    &lt;ul&gt; 标记包裹SiteMapPath 控件,这样就可以了。

    例子:

     <ul class="breadcrumb">
      <asp:SiteMapPath ID="SiteMapPath1" PathSeparator="" runat="server">
       <NodeTemplate>
        <li>
         <a href='<%# Eval("url") %>' title='<%# Eval("description") %>'><%# Eval("title") %></a>
        </li>
       </NodeTemplate>
       <PathSeparatorTemplate>
         <span class="divider">/</span>
       </PathSeparatorTemplate>
      </asp:SiteMapPath>
    </ul>
    

    这是使用 Bootstrap 和 ASP.NET 时的绝佳选择

    【讨论】:

    • 不会在每个列表元素之间放置一个span 吗? ul 元素只能包含 li 元素。
    • 是的,它实际上仍然将跨度放入其中,尽管它们现在包含 li 的。 -1 因为这并不能真正解决 OP 的问题。
    【解决方案4】:

    虽然您无法摆脱跨度标签,但您可以完成您想要的。我遇到了同样的问题,因为我使用的是客户想要的购买的 CSS/HTML 网站模板,但整个事情都是基于 &lt;ul&gt;&lt;li&gt; 的。重构 CSS 太痛苦了,所以我发现这个解决方案运行良好,无需更改 CSS 代码。

    你会做两件事:

    1. 使用使用&lt;li&gt; 标签的节点模板覆盖默认节点模板
    2. 将整个内容包装在&lt;ul&gt; 标签中

    这是一个例子:

    <ul style="list-style-type: none;">
      <asp:SiteMapPath ID="SiteMapPath1" runat="server" >
        <NodeTemplate>
          <li>
            <a href='<%# Eval("url") %>' title='<%# Eval("description") %>'><%# Eval("title") %></a>
          </li>
        </NodeTemplate>
      </asp:SiteMapPath>
    </ul>
    

    【讨论】:

    • 我没有任何方法可以测试这个了,但如果它有效,它会非常适合我的需求。
    • 不工作,它会将 li 呈现在 span 内
    • 虽然有点牵扯,但您可以摆脱跨度。如果您愿意,请查看我对这个问题的回答。
    【解决方案5】:

    我能想到的最接近的方法是将您的站点地图放入&lt;asp:menu&gt; 控件中。然而,这将输出为一个 html 表格,但在视觉上它会显示一个列表:

    <asp:Menu ID="leftNavigation" runat="server" DataSourceID="SiteMapDataSource1" 
           StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1">
    </asp:Menu>
    <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" />
    

    使用所有样式和格式选项来获得所需的输出。 See here 了解详细演练。

    哦,当然,您也可以考虑使用带有站点地图的树视图(参见同一页面)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-28
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2020-06-13
      • 2019-02-26
      • 1970-01-01
      相关资源
      最近更新 更多