Nesse artigo vamos mostrar como criar um menu dinâmico em .Net C#. A ideia é buscar os dados do menu em um banco dados, previamente cadastrado, e montar o menu, de acordo com essas informações. O menu pode ser do tipo que você quiser, no exemplo utilizamos o System.Web.UI.WebControls.Menu
Segue abaixo uma ideia para tabela que armazenará os dados do menu:
CREATE TABLE [dbo].[Menu] ( [ID_Menu] [INT] NOT NULL,-- ID [Name] [VARCHAR](50),-- Nome dos itens do menu [ParentMenu] [INT] NULL,-- ID do item do menu pai [Link] [VARCHAR](250) NULL,-- Link acionado ao clicar no menu [OrderMenu] [INT] NULL, -- Ordem dos itens do menu )
Ok, então todos os itens do menu virão dessa tabela, você precisa ter atenção para cadastrar os itens corretamente, caso contrário o menu ficará errado.
Você deve criar uma rotina para ler a tabela acima e armazenar os dados dentro de um DataSet, feito isso, o código abaixo irá percorrer o dataset montando o menu.
public void MontarMenu(Menu myMenu) { ... foreach(DataRow drMenuItens in dsMenu.Tables[0].Rows) { if (ChecarRoot(drMenuItens)) CriarMenu(myMenu, CriarItem(drMenuItens), null, dsMenu.Tables[0]); } }
Verifique que o método CriarMenu (linha 7) só é chamado quando o método ChecarRoot (linha 6) retorna true. Vamos verificar exatamente o que esse método faz.
private bool ChecarRoot(DataRow rowMenu) { return rowMenu["ParentMenu"].Equals(DBNull.Value); }
O ChecarRoot simplesmente verifica se o item de menu não tem pai, ou seja, é o primeiro menu. Agora vejamos o método CriarItem.
private MenuItem CriarItem(DataRow rowMenu) { MenuItem item = new MenuItem(); if (!rowMenu["Name"].Equals(DBNull.Value)) item.Text = rowMenu["Name"].ToString() if (!rowMenu["ID_menu"].Equals(DBNull.Value)) item.Value = rowMenu["ID_menu"].ToString(); if (!rowMenu["Link"].Equals(DBNull.Value)) item.NavigateUrl = rowMenu["Link"].ToString(); return item; }
O método CriarItem cria o item de menu propriamente dito, de acordo com os valores armazenados na tabela. Caso queira adicionar algum atributo novo ao menu, como um ícone, por exemplo, esse é o lugar.
Agora vem o X da questão, método CriarMenu.
private void CriarMenu(Menu myMenu, MenuItem itemCorrente, MenuItem itemPai, DataTable dtMenu) { if (itemPai == null) myMenu.Items.Add(itemCorrente); else itemPai.ChildItems.Add(itemCorrente); DataRow[] rowsChild = dtMenu.Select("ParentMenu = " + itemCorrente.Value); for (int idx = 0; idx < rowsChild.Length; idx++) { CriarMenu(myMenu, CriarItem(rowsChild[idx]), itemCorrente, dtMenu); } }
Eis o cérebro da coisa… O método CriarMenu… Ele é o método responsável por efetivamente criar o menu. Ele funciona de forma recursiva, pois assim o menu não tem limites de níveis.
Como todo bom programador ou analista, você quer pular o blá blá blá e ir direto ao fonte, certo? Beleza… então baixe o fonte de exemplo e adeque a sua necessidade e lembre-se na natureza nada se cria tudo se transforma.
Update 10/07/2013: Publicado um novo post sobre esse assunto utilizando técnicas mais modernas de programação. Ver post.
Download do arquivo: menu.cs
Enjoy iT
—
Sr. Coelho
Gostou? Visite Artigos do Sr. Coelho para mais dicas.
Como você configurou o Menu, para ficar com esse Layout Bonito? Poderia passar o código, por gentileza?
By: Jaqueline Maria on 07/08/2012
at 15:27
Oi Jaqueline, verifique o método CriarItem(), nele podemos fazer a atribuição de qualquer propriedade do item de menu que estamos montando. Nesse momento vc pode utilizar a propriedade “Icon” e atribuir uma imagem para o seu item de menu.
Exemplo:
menutItem.Icon = new System.Windows.Controls.Image { Source = new BitmapImage(new Uri(“images/sample.png”, UriKind.Relative)) };
By: Sr Coelho on 07/08/2012
at 16:51
Qual versão do VS você usou? De onde vem a classe SecureIT.Security ?
By: Fernando on 22/11/2012
at 17:49
Olá Fernando. Usei o VS 2010, mas deve funcionar em versões anteriores tb.
Quanto a classe SecureIT.Security, ela faz parte de um outro projeto que montei. Na montagem do menu, o sistema chama o método GetMenuTable() dessa classe, que no caso, consulta a tabela no banco de dados, onde está a estrutura do menu (ver exemplo de criação da tabela que eu citei) , ela devolve um dataset de acordo com os dados encontrados no banco, e baseado nesse dataset, o menu será montado.
Espero ter ajudado.
Abraço.
By: Sr Coelho on 22/11/2012
at 21:21
tentei criar um quarto nível de menu, algo como “forum > Abertura > Atração > quarto nivel do menu”, mas ele só foi até o terceiro nível ( “atração”), existe alguma limitação ? você já testou com mais de 3 níveis ?
By: mauricio gotlib on 11/01/2013
at 18:51
Oi Maurício, da maneira como foi criado o menu de exemplo do post, não há limite de níveis, pois a rotina é recursiva, ou seja, ela vai chamando ela mesma e montando quantos níveis houverem cadastrados no banco de dados.
By: Sr Coelho on 11/01/2013
at 20:42
Obrigado Sr Coelho,
realmente a recursividade com que foi desenvolvida sua programação é ilimitada, no meu caso ( talvez interesse para outros que poderão cair na mesma “armadilha”) a limitação estava na propriedade “MaximumDynamicDisplayLevels” do controle Menu do .net., que estava limitada a 3 níveis.
By: mauricio gotlib on 14/01/2013
at 09:46
Boa Maurício, obrigado pela dica. No meu caso eu usei o “System.Windows.Forms.MenuStrip” e ele não tem essa propriedade.
By: Sr Coelho on 14/01/2013
at 11:34
Ótimo guia!!
Sr. Coelho, estou com um probleminha poderia me ajudar ?
Eu utilizei o exemplo que você criou, porém quando eu clico em algum “pai”, ele duplica todos os pais.
O click nos filhos funciona direitinho, mas nos pais não
Poderia me ajudar ?
Obrigado!
By: Rafael on 24/06/2013
at 10:49
Bom dia Rafael.
Primeiramente, obrigado pela visita e pelo comentário.
Bem, não entendi exatamente o seu problema. O menu é montado corretamente e depois quando vc clica em algum item (que é pai) ele da esse problema de duplicar? É isso?
No caso do exemplo, a única coisa que deveria ocorrer quando alguém clica em algum item do menu, é ele acionar a url configurada na tem.NavigateUrl.
By: Sr Coelho on 24/06/2013
at 11:52
Isso, por exemplo, os meus “Pais” são Home, About, Cadastro.
Quando eu clico em algum deles, ele duplica, então fica Home, About, Cadastro. Home, About, Cadastro.
By: Rafael on 24/06/2013
at 12:57
Entendi, mas é como expliquei no outro comentário, a única ação que o menu deveria tomar é a descrita no item.NavigateUrl, será que quando clica no menu vc não está chamando a rotina de criar menu novamente?
Lembre-se de que, se estiver usando páginas aspx, a rotina que aciona a criação do menu deve estar dentro de um if (!Page.IsPostBack), por exemplo:
Espero ter ajudado.
Abraço.
By: Sr Coelho on 24/06/2013
at 14:45
Obrigado. Muito bom teu tutorial!!!
By: Cassiano on 10/07/2013
at 11:05
Obrigado Cassiano. Se quiser verificar um novo post sobre esse assunto, acesse https://srcoelho.com.br/2013/07/09/menu-html-dinamico/
By: Sr Coelho on 10/07/2013
at 11:50
Sr Coelho, Parabéns pelo site! o conteúdo é de primeira”
Poderia me ajudar com uma questão?, estou montando um menu dinamicamente de acordo com o fonte exibido por você acima, o meu problema está na lentidão. Meu menu esta dividido em 5 tabelas, cada tabela representa um nível, logo são 5 níveis. Teria uma dica de como popular o DataSet a ser percorrido? Estou realizando muitos selects pois a cada estrutura, eu realizo um select e populo o dataSet, mas esta operação é lenta.
Grato desde já!
Atenciosamente Rafael T.
By: Rafael T. on 16/05/2014
at 09:59
Tks! me ajudou bastante, troquei o componente utilizando treeview, então nos lugares de item utilizei nodes. Muito obrigado.
By: Salvador on 21/05/2014
at 22:00
Obrigada me ajudou bastante tbm, muito simples, agora meu menu pode ter N niveis rsrs, sempre peno um pouco pra fazer recursividade , agora foi fácil com tudo mastigado, fiz adaptações, usei treeview e ficou jóia.
By: Queren on 25/06/2014
at 16:53
Sr. Coelho o que seria SecureIT.Security
By: Elenilson on 06/11/2016
at 14:33
Elenilson, da uma lida nos comentários que eu explico sobre ele. Vlw.
By: Sr Coelho on 25/03/2017
at 14:50