Controlar Menus visiveis com o web.sitemap
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.