2011-09-29 23 views
11

我对.NET和VB.NET都非常陌生,不能完全弄清楚如何做到这一点。说我有这样的代码:如何将asp:SiteMapPath的输出转换为列表?

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

它输出与>一堆<span> S作为分隔符,这样的事情:

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

回答

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

这是除了伟大的,一切都在节点显示出来:/ – SearchForKnowledge

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的详细演练。

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

2

虽然你不能摆脱span标签,你可以完成你想要的。我遇到了同样的问题,因为我使用的是客户需要购买的CSS/HTML网站模板,但整个事情是基于<ul><li>的。重构CSS本来就太痛苦了,所以我发现这个解决方案在CSS代码没有任何改变的情况下运行良好。

你会做两两件事:

  1. 覆盖与使用<li>标签
  2. 包住整个事情的<ul>标签

这里一个默认的节点模板的一个例子:

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

我没有测试这个了的任何手段,但如果工作就真是已经完美满足我的需求。 –

+3

不工作,它会渲染一个范围内的li –

+0

虽然有一点牵扯,你可以摆脱跨度。如果你喜欢,请看看我对这个问题的回答。 – Marcel

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

这是外观极好选择使用引导和ASP.NET

+0

这不会在每个列表元素之间放置一个“span”吗? 'ul'元素可能只包含'li'元素。 –

+0

是的,它实际上仍然放入跨度,尽管它们现在包含李的。 -1,因为这确实没有解决OP的问题。 – Marcel

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

来自ASP的问题noob:如何注册我的:NakedSiteMapPath,以便您可以在.aspx中使用它? – Fabien