Uma maneira rápida de ter um menu a funcionar no nosso website, é recorrer ao controlo Menu e associá-lo a um web.sitemap usando o SiteMapDataSource.
Exemplo do ficheiro web.sitemap:
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="~/" title="Home" description="Home" >
<siteMapNode url="" description="Menu 1" title="Menu 1">
<siteMapNode url="" description="SubMenu 1" title="Sub Menu 1"/>
</siteMapNode>
<siteMapNode url="" description="Menu 2" title="Menu 2"/>
<siteMapNode url="" description="Menu 3" title="Menu 3"/>
</siteMapNode>
</siteMap>
Exemplo do código para adicionar na página o menu:
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu"
EnableViewState="False" IncludeStyleBlock="False" Orientation="Horizontal"
DataSourceID="SiteMapDataSource1" onmenuitemdatabound="NavigationMenu_MenuItemDataBound">
</asp:Menu>
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" />
Correndo a aplicação, iremos ter algo como a próxima imagem:

Para mostrar ou esconder os menus, consoante o tipo de acesso de cada utilizador, podemos definir as Roles em cada SiteMapNode.
Outra forma de controlar os menus visiveis, é adicionar um atributo em cada SiteMapNode e consoante o seu valor, irá ou não mostrar cada um dos menus.
Para isso, o web.sitemap será algo como:
<?xml version="1.0" encoding="utf-8"?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
<siteMapNode url="~/" title="Home" description="Home" visible="true">
<siteMapNode url="" description="Menu 1" title="Menu 1" visible="true">
<siteMapNode url="" description="SubMenu 1" title="Sub Menu 1" visible="true" />
</siteMapNode>
<siteMapNode url="" description="Menu 2" title="Menu 2" visible="False" />
<siteMapNode url="" description="Menu 3" title="Menu 3" visible="true" />
</siteMapNode>
</siteMap>
O atributo “visible” é que nos vai indicar se o menu é ou não mostrado, e para isso vamos adicionar ao evento MenuItemDataBound do Menu o seguinte código:
protected void NavigationMenu_MenuItemDataBound(object sender, MenuEventArgs e)
{
SiteMapNode node = e.Item.DataItem as SiteMapNode;
if (!string.IsNullOrEmpty(node["visible"]))
{
bool isVisible;
if (bool.TryParse(node["visible"], out isVisible))
{
if (!isVisible)
{
if (e.Item.Parent != null)
e.Item.Parent.ChildItems.Remove(e.Item);
else
((Menu)sender).Items.Remove(e.Item);
}
}
}
}
Desta forma, teremos o nosso menu a mostrar todos os nós cujo valor do atributo Visible seja igual a True.
Para podermos controlar directamente os menus que irão estar ou não visiveis, utilizei uma Treeview para carregar o ficheiro web.sitemap, definir que todos os items mostrarão uma checkbox, que irá indicar o estado do atributo Visible.
<asp:TreeView runat="server" ID="tvMenus" AutoGenerateDataBindings="False" DataSourceID="XmlDsSiteMap"
OnTreeNodeCheckChanged="tvMenus_TreeNodeCheckChanged" ShowCheckBoxes="All" ShowLines="True"
OnTreeNodeDataBound="tvMenus_TreeNodeDataBound">
<DataBindings>
<asp:TreeNodeBinding DataMember="siteMapNode" SelectAction="None" ShowCheckBox="True"
TextField="title" />
<asp:TreeNodeBinding DataMember="siteMapNode" TextField="title" />
<asp:TreeNodeBinding DataMember="siteMapNode" TextField="title" />
<asp:TreeNodeBinding DataMember="siteMap" />
</DataBindings>
</asp:TreeView>
<asp:XmlDataSource ID="XmlDsSiteMap" runat="server" DataFile="~/Web.sitemap" XPath="/*/*/*">
</asp:XmlDataSource>
<p>
<asp:Button runat="server" ID="btn" Text="gravar" OnClick="btn_Click" /></p>
protected void tvMenus_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
XmlElement node = e.Node.DataItem as XmlElement;
if (node.Attributes["visible"] != null)
{
if (!string.IsNullOrEmpty(node.Attributes["visible"].Value))
{
bool isVisible;
if (bool.TryParse(node.Attributes["visible"].Value, out isVisible))
{
e.Node.Checked = isVisible;
}
else
e.Node.Checked = true;
}
else
e.Node.Checked = true;
}
}

Por fim, para gravarmos as alterações do atributo consoante o estado da checkbox, adicionamos ao evento TreeNodeCheckChanged da Treeview o seguinte código:
protected void tvMenus_TreeNodeCheckChanged(object sender, TreeNodeEventArgs e)
{
XmlDsSiteMap.GetXmlDocument().SelectSingleNode(e.Node.DataPath).Attributes["visible"].Value = e.Node.Checked.ToString();
}
E ao botão que adicionamos para gravar as alterações o seguinte código:
protected void btn_Click(object sender, EventArgs e)
{
XmlDsSiteMap.Save();
}
Agora é só activar e desactivar os items ao nosso gosto.
