ASP.NET bietet eine Reihe von vordefinierten Server Controls, die im Wesentlichen ein Pendant in der Windows-Welt haben. Leider vermisst man Controls, die sich direkt mit der Navigation in Webseiten - also innerhalb einer Website - befassen.
Untersucht man Webseiten genauer, so findet man insbesondere auf großen Websites so genannte Sitemaps. Diese beschreiben meist die ersten zwei oder drei Navigationsebenen der gesamten Site und erleichtern dem Benutzer das Auffinden der gewünschten Inhalte. Oftmals werden Sitemaps auch eingesetzt, um Besucher gezielt auf interessante, aber vielleicht schwer zu findende Inhalte aufmerksam zu machen. In der Konzeptionsphase für eine Website verwendet man häufig sehr früh eine Sitemap als Strukturierungsmittel. Zum Projektende enthält die Sitemap Informationen über jede Seite, zum Beispiel mit einer ID, dem Titel, der URL und beliebigen weiteren Informationen. Aus einer solchen Baumstruktur kann man eine formale Beschreibung der Website in XML (siehe Listing 1) erstellen. Navigationselemente lassen sich nach ihrer Funktion klassifizieren (siehe Abb. 1). Listing 1<?xml version="1.0" encoding="utf-8" ?><Sitemap><DefaultFile>default.aspx</DefaultFile><Menu id="0" url="default.aspx" text="Home"></Menu><Menu id="1" url="" text="Speiseplan"><Menu id="1.1" url="" text="Montag"><Menu id="1.1.1" url="" text="Theke -Vegetarisch-"><Menu id="1.1.1.1" url="" text="Gemüsesuppe"></Menu><Menu id="1.1.1.2" url="" text="Tomatensuppe"></Menu><Menu id="1.1.1.3" url="" text="Bohnensuppe"></Menu><Menu id="1.1.1.4" url="" text="Algensuppe"></Menu></Menu><Menu id="1.1.2" url="" text="Theke -Einfach tierisch-"><Menu id="1.1.2.1" url="" text="Rehbraten"></Menu><Menu id="1.1.2.2" url="" text="Sauerbraten"></Menu><Menu id="1.1.2.3" url="" text="Hase in Pfeffer"></Menu></Menu><Menu id="1.1.3" url="" text="Theke -Geniessen-">...</Menu></Menu>...</Menu><Menu id="2" url="newsletterabo.aspx" text="Newsletter-Abo"></Menu><Menu id="3" url="impressum.aspx" text="Impressum"></Menu></Sitemap>
Navigation-Controls
Es gibt drei Arten von Navigations-Kontrollelementen:- TopNavigation. Dieser Navigationstyp zeichnet sich dadurch aus, dass er auf jeder Seite oben erscheint und statisch ist. Die TopNavigation implementiert die erste Kategorisierungsebene (oder Hierarchieebene) einer Website und ist in vielen Fällen mit der ersten Ebene der Hauptnavigation identisch.
- NavigationPath. Der NavigationPath (Beispiel: Home>Speiseplan>Montag) zeigt dem Benutzer an, auf welcher Ebene der Website er sich gerade befindet bzw. welchen Weg er bereits genommen hat. Man kann dies mit den Pfadangaben im Windows Explorer vergleichen, nachdem der Benutzer eine gewisse Ordnerstruktur durchlaufen hat um ein Dokument aufzufinden. Eingesetzt wird der NavigationPath häufig, wenn die Website eine tiefe Navigationsstruktur mit vielen Ebenen aufweist.
- MainNavigation. Die MainNavigation dient der eigentlichen Benutzerführung und ist neben dem Content der flexibelste Teil einer Website.
TopNavigation
Basierend auf diesem Wissen kann man nun die Entwicklung von Navigation-Controls in einer Control-Library angehen. Diese Controls müssen in der Lage sein zu entscheiden, welche Menüpunkte dargestellt werden sollen. Jede der Webseiten einer Site hat feste Menüpunkte, beispielsweise Home, Speiseplan, Newsletter-Abo und Impressum. Aus diesen Informationen lässt sich ein TopNavigation-Control erstellen, das die einzelnen Navigationspunkte aus der ersten Hierarchieebene des XML-Dokumentes bezieht. .NET bietet zwei Arten von Server Controls: zum einen User Controls (abgeleitet von System.Web.UI.TemplateControl) und zum anderen Web Controls (abgeleitet von System.Web.UI.WebControls.WebControl). User Controls sind meist projektspezifisch und besitzen eine eigene .ascx-Datei während Web Controls meist in Bibliotheken verwaltet werden - und somit unabhängig von einer speziellen Webapplikation sind. Für die Implementierung bestehen grundsätzlich folgende Möglichkeiten:- Methode 1: User Control. Der HTML-Code wird in die .ascx-Datei geschrieben und die Ausgabe der Menüpunkte im Code Behind im PageLoad()-Event implementiert. Dieser Ansatz scheidet aus, weil der HTML-Code keinen anwendungsspezifischen C#-Code beinhalten soll.
- Methode 2: User Control. Der HTML-Code wird in die Render()-Methode übernommen. Diese Lösung scheidet ebenfalls aus, weil der HTML-Code bei Fehlern oder neuen Anforderungen schnell und unkompliziert änderbar sein muss. Außerdem soll das Control in einer Control-Library eingebettet sein, um flexibel in mehreren Projekten wiederverwendet werden zu können.
- Methode 3: Web Control. Die XSLT-Transformation wird in der Render()-Methode des Controls durchgeführt. Dieser Ansatz ist vielversprechend: Es befindet sich kein C#-Code im HTML-Quelltext, die Logik liegt im Code Behind und die Web Controls lassen sich in einer Control-Library zusammenfassen.
protected override void Render(HtmlTextWriter output){XmlDocument mydata = new XmlDocument();mydata.Load(menu.xml);
XslTransform xsltransform = new XslTransform();xsltransform.Load(topnavigation.xslt);
xsltransform.Transform(mydata, null, output);}
<?xml version="1.0" encoding="UTF-8" ?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:output method="html"/><xsl:template match="//*"><table border="0" cellspacing="0" cellpadding="5"><tr><xsl:for-each select="Menu"><td>[<a><xsl:attribute name="href"><xsl:choose><xsl:when test="@url=''"><xsl:value-of select="//DefaultFile"/>?id=<xsl:value-of select="@id"/></xsl:when><xsl:otherwise><xsl:value-of select="@url"/></xsl:otherwise></xsl:choose></xsl:attribute><xsl:value-of select="@text"/></a>]</td></xsl:for-each></tr></table></xsl:template></xsl:stylesheet>
NavigationPath
Interessanter ist natürlich der NavigationPath, auch Bread Crumble Path genannt, allein wegen seiner Dynamik. Prinzipiell geht man genauso vor wie bei der Implementierung der TopNavigation. Die wichtigste Information für den NavigationPath ist der aktuelle Menüpunkt, der vom User gewählt wurde, welcher über den Request-Parameter id im PageLoad()-Event des Web Forms ermittelt wird:NavigationPath1.MenuId = Request["id"];
XmlNode CurrentNode = mydata.SelectSingleNode("//Menu[@id='" + m_MenuId + "']");while(CurrentNode.Name != "Sitemap"){copyNode = outputXml.ImportNode(CurrentNode, false);outputXml.DocumentElement.PrependChild(copyNode);CurrentNode = CurrentNode.ParentNode;}
MainNavigation
Die Implementierung der MainNavigation ist genauso einfach wie bei den zuvor vorgestellten Controls. Durch den Request-Parameter (Ermittlung wie oben) erfährt man, welchen Menüpunkt der User gewählt hatte. Ausgehend von diesem Menüpunkt werden alle direkten ChildNodes ermittelt und für das XSL aufbereitet:XmlNode CurrentNode = mydata.SelectSingleNode("//Menu[@id='" + m_MenuId + "']");foreach(XmlNode n in CurrentNode.ChildNodes){copyNode = outputXml.ImportNode(n, false);outputXml.DocumentElement.AppendChild(copyNode);}
MainNavigation1.MenuId = thisMenuId;NavigationPath1.MenuId = thisMenuId;




