• Microsoft .NET
  • ASP.NET
  • Использование элементов управления ListView и DataPager в ASP.NET 3.5

Навигация по сайту в ASP.NET 2.0 - Создаем специализированный пользовательский интерфейс навигации

ОГЛАВЛЕНИЕ

Создаем специализированный пользовательский интерфейс навигации

ASP.NET 2.0 имеет в наличии три элемента управления которые обычно используются для отображения информации из карты сайта:

  • SiteMapPath - отображает пользователю его положение в иерархии карты сайта (Этот элемент управления обсуждался в второй части данной сериии статей.)
  • TreeView - отображает все узлы карты сайта в свертывающимся дереве (treeview)
  • Menu - отображает все узлы в карте сайта, в меню выровненном по горизонтали либо вертикали
Чтобы отобразить информацию карты сайта, оба элемента TreeView и Menu должны быть привязаны к SiteMapDataSource. SiteMapDataSource является элементом управления, возвращающим информацию о карте сайта в TreeView либо Menu в качестве объекта SiteMapNodeCollection, который содержит иерархию узлов. Элементы управления TreeView и Menu рекурсивно проходят по данному набору и выстраивают свои собственные пункты меню и узлы дерева соответственно.

Мы можем работать с SiteMapNodeCollection, возвращенным SiteMapDataSource, либо декларативно, либо программным путем:

<asp:Repeater runat="server"  ID="siteMapAsBulletedList"  DataSourceID="SiteMapDataSource1">
    <HeaderTemplate>
        <ul>
            <li><asp:HyperLink runat="server" ID="lnkHome" NavigateUrl='<%# SiteMap.RootNode.Url %>' Text='<%# SiteMap.RootNode.Title %>'></asp:HyperLink></li>
    </HeaderTemplate>

    <ItemTemplate>
        <li>
            <asp:HyperLink runat="server" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>'></asp:HyperLink>
        </li>
    </ItemTemplate>

    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>

<asp:SiteMapDataSource ShowStartingNode="false" ID="SiteMapDataSource1" runat="server" />

Здесь мы связали Repeater siteMapAsBulletedList с SiteMapDataSource1 элемента управления SiteMapDataSource. Учтите, что SiteMapDataSource возвращает иерархический объект SiteMapNodeCollection. Repeater, не будучи иерархическим элементом управления информацией, всего лишь перечисляет первый уровень результатов узлов карты сайта. То есть он не углубляется в дочерние узлы каждого SiteMapNode. В данном примере ShowStartingNode установлен в значение False, что заставляет SiteMapNodeCollection начать обработку со второго уровня (Books, DVD, Electroincs, и Computers). То есть для каждого SiteMapNode второго уровня инициируется ItemTemplate. (Корневой узел карты сайта (Home) отображается с небольшой разметкой в HeaderTemplate.)

При помощи декларативной разметки, указанной выше, мы получим следующий результат:


Это полезно использовать для отображения корневого узла карты сайта, а также первый уровень. Но что если мы хотим отобразить дополнительные уровни? Мы можем просто добавить другой Repeater в ItemTemplate, тем самым устанавливая DataSource того второго Repeater в свойство ChildNodes текущего используемого узла, примерно так:

<asp:Repeater runat="server"  ID="siteMapAsBulletedList"  DataSourceID="SiteMapDataSource1">
    <HeaderTemplate>...</HeaderTemplate>
    
    <ItemTemplate>
        <li>
            <asp:HyperLink runat="server" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>'></asp:HyperLink>

            <asp:Repeater runat="server" id="SecondLevel" DataSource='<%# CType(Container.DataItem, SiteMapNode).ChildNodes %>'>
                <HeaderTemplate><ul></HeaderTemplate>
                <ItemTemplate>
                    <li>
                        <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>'></asp:HyperLink>
                    </li>
                </ItemTemplate>
                <FooterTemplate></ul></FooterTemplate>
            </asp:Repeater>
        </li>
    </ItemTemplate>
    
    <FooterTemplate>...</FooterTemplate>
</asp:Repeater>

<asp:SiteMapDataSource ShowStartingNode="false" ID="SiteMapDataSource1" runat="server" />

Для C#, свойство DataSource будет установлено как DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'

{mosimage}

Декларативный подход ограничен только отображением тех уровней карты, которые внедрены во множество Repeater. То есть, если узел Romance имел дополнительные подузлы, вышеупомянутая декларативная разметка не включала бы их в себя. Для того чтобы отобразить их, используя декларативную разметку, нам нужно добавить третий Repeater к ItemTemplate второго Repeater. Тем не менее, это не будет отображать все узлы сайта вплоть до 4 уровня.

Чтобы отобразить узлы любой "глубины" в списке нам необходимо программно задействовать SiteMapDataSource и рекурсивно пройтись по возвращенным объектом SiteMapNodeCollection. Следующий код (только в VB) демонстрирует способ реализации данной идеи. На странице присутствует элемент Label с ID bulletedList, и SiteMapDataSource с IDsiteMapData и его свойство ShowStartingNode установлено в значение False. (Данный код, а также все предыдущие примеры, доступны в конце данной статьи...)

Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) _
                                                      Handles Me.Load
  'Создаем список
  bulletedList.Text = _
      String.Format("<ul><li><a href=""{0}"">{1}</a></li>{2}</ul>", _
                    SiteMap.RootNode.Url, SiteMap.RootNode.Title, _
                    DisplaySiteMapLevelAsBulletedList())
End Sub

Private Function DisplaySiteMapLevelAsBulletedList() As String
  'Получаем SiteMapDataSourceView из siteMapData SiteMapDataSource
  Dim siteMapView As SiteMapDataSourceView = _
          CType(siteMapData.GetView(String.Empty), SiteMapDataSourceView)
 
  'Получаем SiteMapNodeCollection из SiteMapDataSourceView
  Dim nodes As SiteMapNodeCollection = _
          CType(siteMapView.Select(DataSourceSelectArguments.Empty), _
          SiteMapNodeCollection)

  'Рекурсивно проходим по SiteMapNodeCollection...
  Return GetSiteMapLevelAsBulletedList(nodes)
End Function

Private Function GetSiteMapLevelAsBulletedList(ByVal nodes As _
                                 SiteMapNodeCollection) As String
    Dim output As String = String.Empty
    For Each node As SiteMapNode In nodes
        output &= String.Format("<li><a href=""{0}"">{1}</a>", _
                                node.Url, node.Title)

        'Добавляем все дочерние уровни , если необходимо (рекурсивно)
        If node.HasChildNodes Then
            output &= String.Format("<ul>{0}</ul>", _
                        GetSiteMapLevelAsBulletedList(node.ChildNodes))
        End If

        output &= "</li>"
    Next

    Return output
End Function


Scott Mitchell

Исходный код примеров:

Часть 1, Часть 2 , Часть 3 , Часть 4 , Часть 5.