.net 如何将asp:SiteMapPath的输出转换为列表?

.net 如何将asp:SiteMapPath的输出转换为列表?,.net,vb.net,.net,Vb.net,我对.NET和VB.NET都非常不熟悉,不太明白如何做到这一点。假设我有这样的代码: <div class="breadcrumb"> <asp:SiteMapPath ID="SiteMapPath1" runat="server"></asp:SiteMapPath> </div> <div class="breadcrumb"> <span id="ctl00_SiteMapPath1"> <

我对.NET和VB.NET都非常不熟悉,不太明白如何做到这一点。假设我有这样的代码:

<div class="breadcrumb">
    <asp:SiteMapPath ID="SiteMapPath1" runat="server"></asp:SiteMapPath>
</div>
<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>
  • 展示

我能想到的最接近的方法是将您的站点地图放入
进行详细演练


哦,当然你也可以考虑将树状视图与站点地图一起使用(参见同一页)。

你现在可能已经解决了这个问题,但是你可以使用这个函数来循环浏览站点地图根节点及其子节点中的所有项,并建立一个嵌套列表

如果您只对顶层感兴趣,则可以删除
If item.HasChildNodes,然后删除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
公共函数SiteMap()作为字符串
返回ListChildNodes(System.Web.SiteMap.RootNode)
端函数
私有函数ListChildNodes(ByVal节点作为System.Web.SiteMapNode)作为字符串
将sb设置为新System.Text.StringBuilder
某人附加(“
    ”) 作为node.ChildNodes中的SiteMapNode的每个项目 sb.Append(String.Concat(“
  • ”) 如果item.HasChildNodes,则sb.Append(ListChildNodes(item)) 下一个 某人追加(“
”) 使某人恢复原状 端函数
对于那些想要C版本的人:

公共字符串站点地图()
{
返回ListChildNodes(System.Web.SiteMap.RootNode);
}
私有字符串ListChildNodes(System.Web.SiteMapNode节点)
{
System.Text.StringBuilder sb=新的System.Text.StringBuilder();
某人加上(“
    ”); foreach(node.ChildNodes中的SiteMapNode项) { sb.Append(string.Concat(“
  • ”); if(item.HasChildNodes) sb.追加(ListChildNodes(项目)); } 某人追加(“
”); 使某人返回字符串(); }
然后在代码中,只需调用即可将字符串输出到页面

<h1>Site Map</h1>
    <%=SiteMap()%>
</div>
站点地图

虽然您无法摆脱span标记,但您可以实现您想要的。我遇到了同样的问题,因为我使用的是客户想要的购买的CSS/HTML站点模板,但整个过程都基于
  • 。重构CSS太痛苦了,所以我发现这个解决方案在不修改CSS代码的情况下运行良好

    您将做两件事:

  • 使用使用
  • 标记的节点模板覆盖默认节点模板
    标签包装整个东西
  • 下面是一个例子:

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

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

    中,可以按需要的格式放置
  • 元素。 在
    中,可以放置分隔符

    标记包装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>
    
      /

    当使用引导和ASP.NET时,这是一个很好的选择。虽然有一点涉及,但这是一个实际删除跨距并呈现干净列表的解决方案

    首先,通过修改
    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。如果稍微涉及,你可以去掉跨度。如果您愿意,请看一下我对这个问题的回答。这会不会在每个列表元素之间放置一个
    span
    ul
    元素只能包含
    li
    元素。是的,它实际上仍然将跨距放入,尽管它们现在包含li-1因为这并不能解决OP的问题。这很好,但节点中的所有内容都会显示:/ASP noob的问题:如何注册my:NakedSiteMapPath以便在.aspx中使用它?
     <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>
    
    /// <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);
        }
    }
    
    <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>