Как включить вывод asp: SiteMapPath в список?

Я очень незнакома с .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>

Ответ 1

Возможно, вы решили это сделать, но вы можете использовать эту функцию для прокрутки всех элементов в корневом каталоге Sitemap и их потомков и создания вложенного списка.

Вы можете удалить 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

Для тех, кому нужна версия С#:

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>

Ответ 2

Пока вы не можете избавиться от тегов span, вы можете выполнить то, что хотите. Я столкнулся с этой же проблемой, потому что я использовал приобретенный шаблон сайта CSS/HTML, который хотел клиент, но все было основано на <ul> и <li>. Рефакторинг CSS был бы слишком болезненным, поэтому я нашел, что это решение хорошо работает без каких-либо изменений в коде CSS.

Вы сделаете две вещи:

  • Переопределить шаблон по умолчанию Node с тем, который использует теги <li>
  • Оберните все это тегом <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>

Ответ 3

Ближайшим, о котором я могу думать, является размещение вашей карты сайта в элементе управления <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" />

Играйте со всеми параметрами стиля и форматирования, чтобы получить желаемый результат. См. здесь для подробного пошагового руководства.

О, и, конечно же, вы могли бы также рассмотреть использование дерева с помощью карты сайта (см. ту же страницу).

Ответ 4

Хотя это немного связано, это решение, которое фактически удаляет промежутки и отображает чистый список.

Во-первых, избавитесь от этих избыточных интервалов, изменив 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, вам нужно будет использовать шаблоны, как уже предлагали другие. Здесь пример части страницы ASPX с NakedSiteMapPath:

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

Ответ 5

Лучшим вариантом для этого является преобразование SiteMapPath для использования шаблонов.

В <NodeTemplate> вы можете разместить элементы <li> в нужном вам формате. В <PathSeparatorTemplate> вы можете поместить разделитель.

Оберните элемент управления SiteMapPath тегами <ul>, и он должен это сделать.

Пример:

 <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