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

时间:2011-09-29 05:47:39

标签: .net vb.net

我对.NET和VB.NET都非常不熟悉,并且无法弄清楚如何做到这一点。说我有这样的代码:

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

它输出一堆<span>>作为分隔符,如下所示:

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

5 个答案:

答案 0 :(得分: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>

答案 1 :(得分:2)

虽然你无法摆脱跨度标签,但你可以完成你想要的任务。我遇到了同样的问题,因为我使用的是客户想要的购买的CSS / HTML网站模板,但整个过程基于<ul><li>。重构CSS本来就太痛苦了,所以我发现这个解决方案运行良好,没有对CSS代码进行任何更改。

你要做两件事:

  1. 使用<li>标记
  2. 覆盖默认节点模板
  3. 将整个内容包裹在<ul>标记
  4. 以下是一个例子:

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

答案 2 :(得分:0)

我能想到的最接近的是将站点地图放入<asp:menu>控件。然而,这将作为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详细演练。

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

答案 3 :(得分:0)

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

首先,通过修改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>

答案 4 :(得分:-1)

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

<NodeTemplate>中,您可以使用所需格式放置<li>元素。 在<PathSeparatorTemplate>中,您可以放置​​分隔符。

使用<ul>标记包装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

时,这是一个很好的选择