Het standard menu van Sharepoint 2010 is op zich prima voor interne sites, echter bij een publieke website wil je hier wel het een en ander aan styling toepassen. Het standaard menu uit Sharepoint 2007 is gelukkig helemaal verbeterd en is tegenwoordig een stuk beter te stylen.

Het menu wordt gedefinieerd als een SharePoint:AspMenu. Dit is eigenlijk gewoon een asp:AspMenu met enkele uitbreidingen voor Sharepoint. Je kunt hier zelf niet van overerven, aangezien het een sealed class is. Er zijn her en der wel oplossingen te vinden waar men uiteindelijk toch in staat is geweest om de code van het menu over te erven. Wanneer er alleen wat gestyled moet worden is dat niet direct nodig, hoewel ik denk dat het toch wel handig kan zijn.

Omdat je eigenlijk werkt met een asp:AspMenu, kun je dus ook je eigen templates maken. Van onze designer had ik de opdracht gekregen dat het menu als hieronder moest worden gerenderd:

<ul class="">
	<li class="selected_menu_item"><a href="/default.aspx" class="link">home</a> </li>
	<li><a href="/Pagina/zwanger.aspx" class="link">zwanger</a> </li>
	<li><a href="/Pagina/baby.aspx" class="link">baby</a> </li>
	<li><a href="/Pagina/peuter.aspx" class="link">peuter</a> </li>
	<li><a href="/Pagina/schoolgaand_kind.aspx" class="link">schoolgaand kind</a> </li>
	<li><a href="/Pagina/puber.aspx" class="link">puber</a> </li>
	<li><a href="/Pagina/jong_volwassene.aspx" class="link">jong volwassene</a> </li>
</ul>

Tijdens m'n ASP.NET tijd had ik al geleerd dat je in het asp:AspMenu gebruik kunt maken van het ItemTemplate blok. Het enige dat ik hoefde te doen is de header en footer (de UL-elementen) boven en onder het menu te plaatsen.

Uiteindelijk is er deze code uit gekomen:

<ul id="main_menu_ul" class="">
	<sharepoint:aspmenu id="TopNavigationMenuV4" runat="server" enableviewstate="false"
		datasourceid="topSiteMap" accesskey="<%$Resources:wss,navigation_accesskey%>"
		usesimplerendering="true" useseparatecss="false" orientation="Horizontal" staticdisplaylevels="1"
		maximumdynamicdisplaylevels="1" skiplinktext="" cssclass="s4-tn">
		<StaticSelectedStyle CssClass="selected_menu_item" />
			<StaticItemTemplate>        
				<li>            
					<a href="<%# DataBinder.Eval(Container.DataItem, "DataPath") %>" class="link">            
						<%# DataBinder.Eval(Container.DataItem, "Text") %>
					</a>
					</li>    
			</StaticItemTemplate>
	</sharepoint:aspmenu>
	<sharepoint:delegatecontrol runat="server" controlid="TopNavigationDataSource" id="topNavigationDelegate">    
		<Template_Controls>        
			<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider"
			id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>        
		</Template_Controls>
	</sharepoint:delegatecontrol>
</ul>

In principe is dit precies wat ik wilde. Alle menu elementen in een li-element stoppen en dat alles in een ul-element.
Bij het bekijken van de pagina leek alles ook goed te gaan, afgezien van een jQuery functie. Bij nadere inspectie van de broncode kwam dit omdat het Sharepoint:AspMenu zelf allerlei elementen aanmaakte met 'nuttige' informatie, hier kon de jQuery functie niet tegen. Omdat het ook niet netjes is om een verschillende elementen binnen een ul-element te hebben moest er dus iets anders worden ontwikkeld.

Omdat je niet een header- en footer template kunt definiëren met een AspMenu kon ik dit eigenlijk al niet meer gebruiken. Gelukkig bestaan er meerdere ASP.NET controls waar gebruik van kan worden gemaakt wanneer je een datasource hebt, zoals een asp:Repeater.

Met een asp:Repeater kun je wel een header- en footertemplate definieren en levert geen onnodige tabellen of andere elementen op. Nadeel van de repeater is wel dat het lastig is om meerdere niveaus te definiëren.

In dit specifieke geval is het niet zo'n enorm probleem dat er maar 1 niveau kan worden gebruikt, omdat er meerdere menu's onder elkaar komen te staan, welke dus allemaal hun eigen asp:Repeater kunnen gebruiken met een eigen datasource.

De code die ik gebruik voor het vullen van het menu is als volgt:

<asp:Repeater ID="TopMenu" runat="server" DataSourceID="cjgSiteMap">
	<HeaderTemplate>
		<ul id="main_menu_ul" class="">
	</HeaderTemplate>
	<ItemTemplate>
		<li><a href="<%# Eval("Url")%>" class="link">
			<%# Eval("Title")%></a></li>
	</ItemTemplate>
	<FooterTemplate>
		</ul>
	</FooterTemplate>
</asp:Repeater>
<asp:SiteMapDataSource SiteMapProvider="CombinedNavSiteMapProvider" ShowStartingNode="false"
	StartFromCurrentNode="false" StartingNodeOffset="0" StartingNodeUrl="sid:1002"
	EnableViewState="true" ID="cjgSiteMap" runat="server" />

Bij de submenu's gebruik ik gewoon een StartingNodeOffset die hoger is, of een van de andere navigation providers welke beschikbaar zijn binnen Sharepoint, een overzicht van 2007 is hier te vinden: http://ktskumar.wordpress.com/2008/04/14/sharepoint-navigation-providers-part-1/ (deze werken over het algemeen ook in Sharepoint 2010).

Het resultaat is het onderstaande voorbeeld:

Ik ben nu blij dat het AspMenu niet naar behoren werkte, aangezien er nu een veel mooiere oplossing is geïmplementeerd voor deze website.

comments powered by Disqus