Le but de cet article est de créer un menu lisse et facile à utiliser pour un site Web compatible ASP.NET. Pour ce faire, nous utiliserons les fonctionnalités standard du contrôle Web ASP.NET Menu et améliorerons l'apparence uniquement en utilisant des feuilles de style en cascade (CSS).
Pour ceux d'entre vous qui connaissent CSS, le titre de cet article sonnera sûrement une cloche. Le CSS utilisé pour améliorer l'apparence et la sensation du contrôle du menu ASP.NET est décrit dans un article largement connu sur une liste à part, intitulé "Portes coulissantes de CSS".
Le CSS utilisé pour améliorer l'apparence du menu est entièrement expliqué dans l'article sur une liste. Crédit lorsque le crédit est dû. Merci Douglas Bowman de nous avoir fourni le CSS. Assurez-vous de lire d'abord son article si vous ne le connaissez pas.
L'objectif de cet article est sur la façon de simuler un tel menu dans un environnement ASP.NET. Commençons ...
Lançons Visual Studio 2008 et créons un nouveau projet à l'aide du modèle de projet d'application Web ASP.NET. Ce modèle ajoutera automatiquement un formulaire Web par défaut nommé de manière appropriée "Default.aspx". Ouvrez-le dans l'éditeur et ajoutez la commande de menu à partir de la boîte à outils que vous pouvez trouver sous l'onglet Navigation. Si vous exécutez le site Web maintenant, vous finirez par regarder une page vierge. Pour que le menu affiche tout ce qu'il doit d'abord être lié à certaines données.
Le moyen le plus simple de définir les données pour le contrôle du menu à utiliser et permettre aux visiteurs de naviguer sur le site Web est de le lier à un site de site. Ajoutez un nouvel élément de carte de site au projet à l'aide du nom proposé de "web.sitemap". La carte du site est un fichier XML qui organise les pages du site de manière hiérarchique. Un avantage supplémentaire est qu'il est automatiquement référencé par le contrôle de SiteMapDataSource.
Ensuite, ajoutez des pages au site du site comme affiché dans la liste ci-dessous.
Listing 1 - web.sitemap
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< siteMap xmlns = " http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 " >
< siteMapNode url = " " title = " " description = " " >
< siteMapNode url = " Default.aspx " title = " Home " description = " Take me back to the dasboard " />
< siteMapNode url = " Products.aspx " title = " Products " description = " Browse our catalog " />
< siteMapNode url = " Download.aspx " title = " Download " description = " Download neat stuff " />
< siteMapNode url = " Forum.aspx " title = " Forum " description = " Ask questions on our forum " />
< siteMapNode url = " Contact.aspx " title = " Contact " description = " Contact us " />
</ siteMapNode >
</ siteMap >Ajoutez maintenant un contrôle SiteMapDataSource à la page et définissez la propriété DataSourceId du contrôle de menu à l'ID de la source de données. Définissez également la propriété d'orientation de la commande de menu sur horizontal car il est par défaut vers la verticale. Enfin, définissez la propriété ShowstartingNode du SiteMapDataSource sur FALSE. Si vous ne le faites pas, seul le nœud racine sera affiché et nous ne voulons pas inclure ce nœud de base dans le menu. Votre code devrait maintenant ressembler au code affiché dans Listing 2.
Listing 2 - Default.aspx
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
> </ asp:Menu >
< asp:SiteMapDataSource
ID =" SiteMapDataSource1 "
runat =" server "
ShowStartingNode =" False "
/>Si vous affichez la page dans un navigateur maintenant, vous devriez voir un menu fonctionnel mais ennuyeux.
Figure 1 - menu horizontal ordinaire

Avant de pouvoir commencer à appliquer CSS au menu, un autre problème doit être résolu en premier. Si vous jetez un œil au code HTML résultant qui est généré lorsque vous demandez la page default.aspx, vous remarquerez que le contrôle de menu ne génère pas le code HTML le plus flexible. Par défaut, il enveloppe chaque élément de menu dans une table. Cela ne se prête pas à appliquer facilement le CSS. Il serait préférable que le contrôle du menu génére une liste UnOrderERDD qui contient tous les éléments de menu.
Heureusement, le HTML généré peut être ajusté en utilisant des adaptateurs de contrôle. Les adaptateurs de contrôle vous permettent de rendre le HTML que vous préférez. Heureusement, ces adaptateurs de contrôle sont facilement disponibles sur CodePlex. Le kit CSS Friendly Control Adapters fournit des adaptateurs de contrôle prédéfinis, y compris un pour le contrôle du menu ASP.NET.
Pour utiliser les adaptateurs de contrôle convivial CSS, suivez ces étapes:
Il est nécessaire d'utiliser le code source et de compiler le CSSFriendly.DLL nous assembler parce que nous devons modifier certains des CS utilisés par les adaptateurs plus tard dans cet article.
Lors de l'ajout du projet CSSFriendly à votre solution, l'assistant de conversion Visual Studio apparaîtra. Exécutez simplement la conversion, tout devrait se passer bien. Lorsque la conversion a terminé tout ce qui reste, c'est ajouter une référence au projet CSSFriendly du projet de site Web ASP.NET.
Exécutez simplement le site Web et jetez un œil au code HTML généré maintenant.
Listing 3 - code HTML sympathique CSS
< div class =" AspNet-Menu-Horizontal " id =" Menu1 " >
< ul class =" AspNet-Menu " >
< li class =" AspNet-Menu-Leaf AspNet-Menu-Selected " >
< a
href =" /Default.aspx "
class =" AspNet-Menu-Link AspNet-Menu-Selected "
title =" Take me back to the dasboard "
> Home </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Products.aspx "
class =" AspNet-Menu-Link "
title =" Browse our catalog "
> Products </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Download.aspx "
class =" AspNet-Menu-Link "
title =" Download neat stuff "
> Download </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a
href =" /Forum.aspx "
class =" AspNet-Menu-Link "
title =" Ask questions on our forum "
> Forum </ a
>
</ li >
< li class =" AspNet-Menu-Leaf " >
< a href =" /Contact.aspx " class =" AspNet-Menu-Link " title =" Contact us "
> Contact </ a
>
</ li >
</ ul >
</ div >Les choses s'améliorent maintenant.
Remarque : Le fichier CSSFriendLyAdapters.browser vous permet de spécifier quels adaptateurs de contrôle convivial CSS doivent être utilisés. Je fais un Habbit de commenter tous les adaptateurs sauf ceux que je veux utiliser. De cette façon, aucun autre contrôle n'est "adapté" et ils continueront de générer le HTML par défaut.
Comme vous pouvez le voir sur le code affiché dans la liste ci-dessus, l'adaptateur pour le contrôle de menu injecte automatiquement les classes CSS nécessaires pour les balises <ul> , <li> et <a> . Cela nous évite de devoir les définir.
Il est également assez courant pour une seule page de contenir plus d'un seul contrôle d'adaptateur, comme un menu. Si vous voulez une apparence distincte pour chaque contrôle, définissez la CSSSeLectorClass pour le contrôle adapté. Par exemple, vous pouvez définir la valeur de la propriété CSSSelectorClass comme suit:
Listing 4 - propriété CSSSelectorClass
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
> </ asp:Menu > Le résultat est que le code HTML généré par le contrôle adapté sera contenu dans une nouvelle couche ( <div> ).
Listing 5 - Emballage du code HTML généré
< div class =" PrettyMenu " id =" Menu1 " >
<!-- Other HTML code -->
</ div >Notez que cette propriété est spécifique aux adaptateurs amicaux CSS. Il s'agit d'un attribut personnalisé (expando) que vous pouvez définir pour les contrôles pris en charge par cette bibliothèque. IT Vous avez besoin de plus d'informations sur le fonctionnement des adaptateurs amicaux, puis consultez les liens suivants:
Avec le CSSSeLectorClass générant une couche séparée ( <div> ) autour du menu et les classes CSS injectées automatiquement en place, nous sommes enfin prêts à commencer le menu.
Le CSS utilisé est simulé à celui de l'article A List. Comme mentionné précédemment, l'objectif de cet article n'est pas sur la structure du CSS, mais plutôt sur la façon de l'appliquer au contrôle du menu ASP.NET afin d'obtenir un menu tabulaire à l'air soigné. Le résultat fini peut être vu sur la figure 2.
Figure 2 - Le résultat fini

Sur la page de téléchargement, vous pouvez trouver le code source de cet article. Il contient la feuille de style et les images nécessaires. Effectuez simplement les étapes suivantes pour recréer le résultat fini:
<Pages> par défaut. (Voir Listing 6)Listing 6 - web.config extrait
< system .web>
<!-- ... -->
< pages theme = " Default " >
<!-- ... -->
</ pages >
<!-- ... -->
</ system .web>Le CSS utilisé dans ma solution est similaire à celui de l'article sur une liste, mais il y a quelques changements. Les modifications sont principalement en corrélation avec la structure CSS appliquée par les adaptateurs amicaux CSS.
Afin d'appliquer le CSS, la structure correcte doit être utilisée. Lorsque vous stylisez un contrôle dont le HTML est ajusté par un adaptateur amical, je trouve pratique d'utiliser des diagrammes mentionnés dans le livre blanc. Ces diagrammes vous montrent clairement comment le CSS est structuré.
Vous pouvez trouver le diagramme du contrôle du menu ici.
Une question que je me suis souvent présentée sur de nombreux forums est de savoir comment implémenter un sous-menu horizontal qui change lorsque l'utilisateur sélectionne un onglet différent dans le menu de niveau supérieur. Pour créer cela, nous devons d'abord ajuster notre carte de site.
Listing 7 montre la carte du site ajustée.
Listing 7 - web.sitemap avec "sous-menu Éléments"
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< siteMap xmlns = " http://schemas.microsoft.com/AspNet/SiteMap-File-1.0 " >
< siteMapNode url = " " title = " " description = " " >
< siteMapNode url = " Default.aspx " title = " Home " description = " Take me back to the dasboard " >
< siteMapNode url = " About.aspx " title = " About us " description = " " />
< siteMapNode url = " Foo.aspx " title = " Foo " description = " " />
< siteMapNode url = " Bar.aspx " title = " Bar " description = " " />
</ siteMapNode >
<!-- ... -->
</ siteMap >Pour la liste de saké de Brevity, 7 affiche uniquement les éléments du sous-menu (nœuds) pour le nœud domestique. Consultez le Web.SiteMap dans le code source de la version complète. Maintenant, lorsque vous parcourez le site Web à l'aide de ce site de site, vous verrez l'effet illustré à la figure 3.
Figure 3 - Éléments de sous-menu

Pour désactiver cet effet, définissez la propriété MaximumDynamicDisplayLevels du contrôle de menu à zéro comme indiqué dans Listing 8.
Listing 8 - MAXIMUMDAMICDISPlayLevels Property
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
MaximumDynamicDisplayLevels =" 0 "
> </ asp:Menu >Ajoutez ensuite un deuxième menu et un contrôle SiteMapDataSource et définissez leurs propriétés comme indiqué dans Listing 9.
Listing 9 - Contrôle du sous-menu
< asp:Menu
ID =" Menu1 "
runat =" server "
DataSourceID =" SitemapDataSource1 "
Orientation =" Horizontal "
CssSelectorClass =" PrettyMenu "
MaximumDynamicDisplayLevels =" 0 "
>
</ asp:Menu >
< asp:Menu
ID =" Menu2 "
runat =" server "
DataSourceID =" SitemapDataSource2 "
Orientation =" Horizontal "
CssSelectorClass =" PrettySubMenu "
>
</ asp:Menu >
< asp:SiteMapDataSource
ID =" SiteMapDataSource1 "
runat =" server "
ShowStartingNode =" False "
/>
< asp:SiteMapDataSource
ID =" SiteMapDataSource2 "
runat =" server "
StartingNodeOffset =" 1 "
ShowStartingNode =" False "
/>Nous disons essentiellement au deuxième menu qu'il devrait afficher le deuxième niveau de nœuds trouvés sur la carte du site et qu'il ne devrait pas afficher le nœud de départ qui correspond à l'onglet sélectionné du premier menu.
Le CSSSeLectorClass pour le deuxième menu est également défini sur PrettySubMenu. Le CSS de ce menu est simulé au premier menu. Téléchargez le code source si vous souhaitez le vérifier. L'exécution du site Web maintenant vous donnera ce résultat Spiffy.
Figure 4 - Éléments de sous-menu stylisés

Un dernier problème doit être résolu. Afin d'illustrer ce numéro, le projet doit être réorganisé.
Ajoutons d'abord une page maître au projet appelé site.master. Déplacez le code, les menus et les sources de données, de la page default.aspx vers la page maître et la placent juste avant le premier porte-greffe de contenu dans le corps. Ensuite, vous pouvez supprimer en toute sécurité la page default.aspx.
Ajoutons maintenant quelques éléments de formulaire de contenu Web au projet. Ajoutez des formulaires de contenu Web qui correspondent aux éléments du premier nœud de la carte du site et de ses sous-nœuds, à savoir:
Assurez-vous de choisir Site.master comme page maître pour chacun de ces formulaires de contenu Web. Les autres pages mentionnées dans le Web.SiteMap sont purement là à des fins illustratives.
Lancez à nouveau le site et accédez à la page FOO. Cela révélera le problème.
Figure 5 - Problème de sélection

Parce que nous avons navigué vers le niveau inférieur sur la carte du site, le menu de niveau supérieur ne sait pas quel élément de menu il doit marquer comme sélectionné. Nous aurons besoin de faire du codage dans le code de la page maître pour résoudre ce problème.
L'inscription 10 vous montre le morceau de code nécessaire.
Listing 10 - Sélection de l'élément de menu de haut niveau correct
namespace MenuWebApplication
{
public partial class Site : System . Web . UI . MasterPage
{
private static string ExtractBaseUrl ( string url )
{
return url . Contains ( "?" ) ? url . Remove ( url . IndexOf ( '?' ) ) : url ;
}
protected void Page_Load ( object sender , EventArgs e )
{
Menu1 . DataBind ( ) ;
// Which node in the site map is currently selected?
SiteMapNode currentNode = SiteMap . CurrentNode ;
if ( currentNode != null )
{
// Obtain the Url of the currently selected node's parent node.
string parentUrl = String . Empty ;
SiteMapNode parentNode = currentNode . ParentNode ;
if ( parentNode != null )
{
parentUrl = ExtractBaseUrl ( parentNode . Url ) ;
}
// Obtain the Url of the currently selected node.
string currentUrl = ExtractBaseUrl ( currentNode . Url ) ;
// Iterate the top level menu tier.
foreach ( MenuItem menuItem in Menu1 . Items )
{
// Compare the menu item's Url against the currently
// selected node's Url or the Url of its parent.
string menuItemUrl = ExtractBaseUrl ( menuItem . NavigateUrl ) ;
if ( ( currentUrl == menuItemUrl ) || ( parentUrl == menuItemUrl ) )
{
// If either matches then mark the top level menu item as selected.
Menu1 . Items [ Menu1 . Items . IndexOf ( menuItem ) ] . Selected = true ;
break ;
}
}
}
}
}
}Vous êtes maintenant libre de sélectionner l'un des éléments du sous-menu. Son élément de menu de haut niveau correspondant restera sélectionné pour donner au visiteur un indice visuel quant à l'endroit où il est actuellement situé dans le site Web.
Figure 6 - Problème de sélection résolu

C'est un peu de travail pour établir un menu tabulaire sophistiqué avec un sous-menu horizontal sensible au contexte, mais à la fin, vous vous retrouvez avec un menu lisse et convivial.
Je vous suggère d'implémenter un tel menu dans un contrôle utilisateur et d'inclure ce contrôle utilisateur sur la page maître de votre site Web. Dans la plupart des cas, un de ces menu sera utilisé sur tout le site Web.