EPiServer web controls: MenuList and PageTree
Posted on August 16, 2009 by Frederik Vig in EPiServerBoth the MenuList and PageTree control are controls that you’ll come across when building the navigation for your EPiServer site. Usually you’ll start out with the MenuList for the main navigation, and use the PageTree for the sub navigation.
MenuList
Templates
A few of its public properties.
- EnableVisibleInMenu – show pages that have visible in menu unchecked
- EvaluateHasChildren
- ExpandAll
- ExpandNodeIfStartPage
- NumberOfLevels
- PageLink
- PageLinkProperty
- RequiredAccess
- ShowRootPage
- SortBy
- SortDirection
- SortOrder
Examples
By default the MenuList will filter out pages that are not published or that the user has no access to. It will also filter out pages where the property visible in menu is unchecked.
<EPiServer:MenuList runat="server" ID="MainMenu"> <HeaderTemplate><ul id="MainMenu"></HeaderTemplate> <ItemTemplate><li><EPiServer:Property runat="server" PropertyName="PageLink" /></li></ItemTemplate> <SelectedTemplate><li><EPiServer:Property runat="server" CssClass="active" PropertyName="PageLink" /></li></SelectedTemplate> <FooterTemplate></ul></FooterTemplate> </EPiServer:MenuList>
protected override void OnLoad(EventArgs e) { base.OnLoad(e); MainMenu.PageLink = PageReference.StartPage; MainMenu.DataBind(); }
Markup rendered
<ul id="MainMenu"> <li><a href="/en/News/">News</a></li> <li><a href="/en/Events/">Events</a></li> <li><a href="/en/Documents/">Documents</a></li> <li><a class="active" href="/en/Examples/">Examples</a></li> </ul>
Separator template
I don’t use the separator template often. However, sometimes I need to add a class to distinguish the first li element.
<ul id="MainMenu"> <li class="first"><a href="/en/News/">News</a></li> <li><a href="/en/Events/">Events</a></li> <li><a href="/en/Documents/">Documents</a></li> <li><a class="active" href="/en/Examples/">Examples</a></li> </ul>
To do this I use a combination of the header and separator template.
<EPiServer:MenuList runat="server" ID="MainMenu"> <HeaderTemplate><ul id="MainMenu"><li class="first"></HeaderTemplate> <ItemTemplate><EPiServer:Property runat="server" PropertyName="PageLink" /></li></ItemTemplate> <SelectedTemplate><EPiServer:Property runat="server" CssClass="active" PropertyName="PageLink" /></li></SelectedTemplate> <SeparatorTemplate><li></SeparatorTemplate> <FooterTemplate></ul></FooterTemplate> </EPiServer:MenuList>
Sometimes you need to add a few span tags inside the anchors. Mostly just for adding more background images. When this happens you cannot use the EPiServer:Property control for this. Instead you use a combination of regular HTML and data binding syntax.
<ItemTemplate> <li> <a href="<%# Container.CurrentPage.LinkURL %>"> <span class="l"></span><span class="c"><%# Container.CurrentPage.Property["PageName"].ToWebString() %></span><span class="r"></span> </a> </li> </ItemTemplate>
PageTree
The PageTree control is the one I use when I need a more complex navigation than a simple list. It has a lot of templates that help with most things I come a cross. However it can be a little hard at first to know which of the templates to use.
- HeaderTemplate
- FooterTemplate
- ItemTemplate
- ExpandedItemTemplate
- ExpandedTopTemplate
- IndentTemplate
- SelectedExpandedItemTemplate
- SelectedExpandedTopTemplate
- SelectedItemTemplate
- SelectedTopTemplate
- TopTemplate
- UnindentTemplate
Both MenuList and PageTree inherit from PageTreeData, which means they have almost identical public properties. They also share the same default filtering settings.
I think the easiest way to show you what the different templates do is with an example.
<EPiServer:PageTree ShowRootPage="false" runat="server" id="SubMenu"> <HeaderTemplate> <div id="SubMenu"><!-- HeaderTemplate --> </HeaderTemplate> <IndentTemplate> <ul> <!-- IndentTemplate --> </IndentTemplate> <ItemHeaderTemplate> <li> <!-- ItemHeaderTemplate --> </ItemHeaderTemplate> <ItemTemplate> <EPiServer:Property PropertyName="PageLink" runat="server" /> <!-- ItemTemplate --> </ItemTemplate> <ExpandedItemTemplate> <EPiServer:Property runat="server" PropertyName="PageLink" CssClass="ExpandedItemTemplate" /> <!-- ExpandedItemTemplate --> </ExpandedItemTemplate> <ExpandedTopTemplate> <EPiServer:Property runat="server" PropertyName="PageLink" CssClass="ExpandedTopTemplate" /> <!-- ExpandedTopTemplate --> </ExpandedTopTemplate> <SelectedItemTemplate> <EPiServer:Property CssClass="SelectedItemTemplate" PropertyName="PageName" runat="server" /> <!-- SelectedItemTemplate --> </SelectedItemTemplate> <SelectedExpandedItemTemplate> <EPiServer:Property runat="server" PropertyName="PageLink" CssClass="SelectedExpandedItemTemplate" /> <!-- SelectedExpandedItemTemplate --> </SelectedExpandedItemTemplate> <SelectedExpandedTopTemplate> <EPiServer:Property runat="server" PropertyName="PageLink" CssClass="SelectedExpandedTopTemplate" /> <!-- SelectedExpandedTopTemplate --> </SelectedExpandedTopTemplate> <ItemFooterTemplate> </li> <!-- ItemFooterTemplate --> </ItemFooterTemplate> <UnindentTemplate> </ul> <!-- UnindentTemplate --> </UnindentTemplate> <FooterTemplate> </div> <!-- FooterTemplate --> </FooterTemplate> </EPiServer:PageTree>
To connect our MainMenu (MenuList) with our newly created SubMenu (PageTree), we’ll use MenuLists OpenTopPage property (returns a PageReference to the open top page).
public MenuList MenuList { get { return _menuList; } set { _menuList = value; } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); SubMenu.PageLink = MenuList.OpenTopPage; SubMenu.DataBind(); }
We need to connect the main menu with the sub menu. Set the MenuList property in your master page.
// The registered user controls for the main and sub menu ... <public:MainMenu runat="server" ID="MainMenu" /> ... <public:SubMenu runat="server" ID="SubMenu" />
protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); if (SubMenu != null && MainMenu != null) { SubMenu.MenuList = MainMenu.MenuList; } ... }
The markup rendered should look something like this.
<div id="SubMenu"><!-- HeaderTemplate --> <ul> <!-- IndentTemplate --> <li> <!-- ItemHeaderTemplate --> <a href="/en/Examples/File-explorer/">File Explorer</a> <!-- ItemTemplate --> </li> <!-- ItemFooterTemplate --> <li> <!-- ItemHeaderTemplate --> <a href="/en/Examples/Registration/">Registration</a> <!-- ItemTemplate --> </li> <!-- ItemFooterTemplate --> <li> <!-- ItemHeaderTemplate --> <a href="/en/Examples/Subscribe/">Subscribe</a> <!-- ItemTemplate --> </li> <!-- ItemFooterTemplate --> <li> <!-- ItemHeaderTemplate --> <a href="/en/Examples/Demo/">Demo</a> <!-- ItemTemplate --> </li> <!-- ItemFooterTemplate --> <li> <!-- ItemHeaderTemplate --> <a href="/en/Examples/Search/">Search</a> <!-- ItemTemplate --> <li> <!-- ItemHeaderTemplate --> <a class="ExpandedTopTemplate" href="/en/Examples/Contact/">Contact</a> <!-- ExpandedTopTemplate --> <ul> <!-- IndentTemplate --> <li> <!-- ItemHeaderTemplate --> <a class="ExpandedItemTemplate" href="/en/Examples/Contact/Test/">Test</a> <!-- ExpandedItemTemplate --> <ul> <!-- IndentTemplate --> <li> <!-- ItemHeaderTemplate --> <a class="SelectedExpandedItemTemplate" href="/en/Examples/Contact/Test/Test2/">Test2</a> <!-- SelectedExpandedItemTemplate --> </li> <!-- ItemFooterTemplate --> </ul> <!-- UnindentTemplate --> </li> <!-- ItemFooterTemplate --> </ul> <!-- UnindentTemplate --> </li> <!-- ItemFooterTemplate --> </ul> <!-- UnindentTemplate --> </div> <!-- FooterTemplate -->
I recommend clicking around a little to see when the different selected templates kick in.

Alex Judd says:
Post Author March 26, 2010 at 17:17Hi Frederik
Love your articles – better than the official EPiServer documentation by a long way!
In the above example, when you get to the PageList control you refer to the MenuList object as ‘MenuList’ when I think it would probably be correct to refer to it as ‘MainMenu’ as that is the instance that you created with the MenuList object in the first MenuList example?
As you can see we’re learning very very slowly here
Alex
Frederik Vig says:
Post Author March 28, 2010 at 13:37Hi Alex
Thanks for the feedback! I’ve updated the post now (was some code missing).
Frederik
Alex Judd says:
Post Author March 29, 2010 at 15:21Hi Frederik
That makes much more sense
I was assuming that in order for the PageTree object to know the ‘OpenTopPage’ of the MenuList it would use the MenuList object we created for the Primary Navigation (called ‘MainMenu’)…
However the code you’ve added makes total sense as you simply create a new MenuList object, a tad confusingly also called ‘MenuList’ [nb: EPiServer do the same in their example so it must be standard confusing practice!] and then ask that to tell us it’s ‘OpenTopPage’ instead.
Let me know if I’m reading the code wrong here!
Thanks again
Alex
Frederik Vig says:
Post Author March 29, 2010 at 17:59We’re using the MenuList controller you created for your main navigation by making it available through a publich property (MenuList), which we then use to set SubMenu’s public MenuList property. We then set SubMenu’s PageLink property to the main navigations OpenTopPage (which holds a PageReference to the “top” page that the user is on).
Hope this helps.
Frederik
Frank says:
Post Author March 16, 2011 at 15:02Hi Frederik,
I have some trouble with this gettin a “Object reference not set to an instance of an object” on the SubMenu.PageLink = MenuList.OpenTopPage;
Any ideas?
Frank says:
Post Author March 16, 2011 at 16:45Problem solved!
I needed to use OnInit insted of OnLoad in MainMenu.ascx.cs
Mathias Nohall says:
Post Author June 27, 2011 at 14:46Hi!
Nice Guide! Helped me alot. Thanks!
However I am trying to use my submenu on somee selected pages only. For example I have a newslist page type where I list the subfoldered news item page types in a a menulist.
So when the sub menu container is in the masterpagefile, every single news item ends up in the sub menu. And I cant uncheck the “enable in menus” checkbox since then all my news dissapears from the list ( due to that I display them in a menulist ).
I have been working on a solution to my problem where I display my submenu in a standard page type template and not my news list page type template. However I canot bind the submenu and the mainmenu objects ” SubMenu.MenuList = MainMenu.MenuList; ” since the mainmenu is in the masterpagefile.
any ideas?
Mathias Nohall says:
Post Author June 27, 2011 at 15:36Hello again!
I solved my problem. I used the newslist control instead of the menulist control and disabled the news item pages in admin mode and it worked