Búsqueda personalizada

jueves, 11 de septiembre de 2008

Menu Jerarquico dinamico

Se que pueden haber muchas formas de realizar esto pero es una de las formas que yo he realizado en combinación de varias tecnologías. A continuación describo como se realiza paso a paso.
Primero que nada crearemos la estructura de nuestro menú en una tabla la cual tendrá el siguiente diseño:



Explico el diseño de esta tabla:

1. IdMenu - es la llave principal de la tabla.
2. DescripcionMenu - Podemos colocar que significa en forma descriptiva del menú.
3. Orden - Va ser el orden vertical, en el que queramos que parezca la opción del menú.
4. Menu - El texto que aparecerá en el menú.
5. URL - Dirección a la que se va dirigir cuando se seleccione el menú.
6. IdMenuPadre - Este va a ser el IdMenu al que pertenezca la opción.
7. IdEstatusMenu - Podemos activar o desactivar esta opción con este campo.
8. Icono - Si queremos anexar un Icono a nuestro menú.
9. IdRol - Si tenemos dividos permisos en nuestra aplicación podemos colocar a que Rol o permiso le otorgamos la visibilidad de este menú.
10. OrdenMenu - A diferencia de la opcion Orden Horizontal

También Coloco tres tablas que utilizaremos también que son la de Gen_REmpleadoRol, Gen_TEmpleado, Gen_TRol (pueden variar según el diseño de su aplicación) en donde guardaremos que Rol desempeña cada uno de los empleados que tienen acceso al sistema para así mostrar el menú según los permisos que tengan:









A Continuación coloco el Store Procedure que utilizaremos para extraer los datos del menú en forma recursiva ya que recordemos que en la misma tabla tenemos elementos que dependen de otros elementos ( IdMenuPadre ):

ALTER PROCEDURE [dbo].[PF_Menu]
@p_IdEmpleado Int = 1
AS
BEGIN
-- EXECUTE PF_Menu 1

WITH Temp_Menu (IdMenu, IdMenuPadre, Menu, Icono, URL, Orden, IdRol, OrdenMenu)
AS
(
SELECT IdMenu, IdMenuPadre, Menu, Icono, URL, Orden, IdRol, OrdenMenu
FROM Gen_TMenu
WHERE IdEstatusMenu = 1
),
Menu_tree AS
(
SELECT Temp_Menu.IdMenu
, IdMenuPadre
, Menu
, Icono
, URL
, 1 As Nivel
, Orden
, OrdenMenu
FROM Temp_Menu
INNER JOIN Gen_REmpleadoRol ON Temp_Menu.IdRol = Gen_REmpleadoRol.IdRol
WHERE Gen_REmpleadoRol.IdEmpleado = @p_IdEmpleado
UNION ALL
SELECT RI.IdMenu
, RI.IdMenuPadre
, RI.Menu
, RI.Icono
, RI.URL
, Nivel + 1
, RI.Orden
, RI.OrdenMenu
FROM Temp_Menu RI
INNER JOIN Menu_Tree MTI ON RI.IdMenu = MTI.IdMenuPadre
)
SELECT MIN(IdMenu) IdMenu
, MIN(ISNULL(IdMenuPadre, IdMenu)) As IdMenuPadre
, Menu
, Icono
, URL
, Orden
, OrdenMenu
FROM Menu_tree
GROUP BY Menu
, Icono
, URL
, Orden
, OrdenMenu
ORDER BY OrdenMenu, Orden


No me detendré a explicar como funciona este stored procedure por que no es el alcance de este artículo. A continuación coloco el Código de nuestra página aspx o master Page en el que queramos incluir nuestro Menu y Nuestro Codigo:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default2.aspx.vb" Inherits="Operaciones_Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Menu ID="Menu1" runat="server" Orientation="Horizontal" BackColor="#FFFBD6" DynamicHorizontalOffset="2" Font-Names="Verdana" Font-Size="XX-Small" ForeColor="#990000" StaticSubMenuIndent="10px" MaximumDynamicDisplayLevels="4">
<StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
<DynamicHoverStyle BackColor="#990000" ForeColor="White" />
<DynamicMenuStyle BackColor="#FFFBD6" />
<StaticSelectedStyle BackColor="#FFCC66" />
<DynamicSelectedStyle BackColor="#FFCC66" />
<DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
<StaticHoverStyle BackColor="#990000" ForeColor="White" />
</asp:Menu>
<asp:ObjectDataSource ID="ODS_PF_Menu" runat="server" OldValuesParameterFormatString="original_{0}"
SelectMethod="GetData" TypeName="DS_MenuTableAdapters.PF_MenuTableAdapter">
<SelectParameters>
<asp:Parameter Name="p_IdEmpleado" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
</div>
</form>
</body>
</html>


Y a Continuación el código VB:

Imports System.Data.SqlClient
Imports System.Data


Partial Class Operaciones_Default2
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Try


Dim DS_Temporal As New DataSet
Dim DV_Temporal As New DataView
Dim dtMenu As New DataTable
Dim Cookie_IdEmpleado As System.Web.HttpCookie
Cookie_IdEmpleado = Request.Cookies("id")

ODS_PF_Menu.SelectParameters("p_IdEmpleado").DefaultValue = Cookie_IdEmpleado.Value
DV_Temporal = ODS_PF_Menu.Select

dtMenu = DV_Temporal.Table


For Each drMenuItem As Data.DataRow In dtMenu.Rows
'esta condicion indica q son elementos padre.
If drMenuItem("IdRecurso").Equals(drMenuItem("IdPadre")) Then
Dim mnuMenuItem As New MenuItem
mnuMenuItem.Value = drMenuItem("IdRecurso").ToString
mnuMenuItem.Text = drMenuItem("Menu").ToString
mnuMenuItem.ImageUrl = drMenuItem("Icono").ToString
mnuMenuItem.NavigateUrl = drMenuItem("Url").ToString
'agregamos el Item al menu
Menu1.Items.Add(mnuMenuItem)
'hacemos un llamado al metodo recursivo encargado de generar el arbol del menu.
AddMenuItem(mnuMenuItem, dtMenu)
End If
Next
Catch ex As Exception

End Try

End If
End Sub

Private Sub AddMenuItem(ByRef mnuMenuItem As MenuItem, ByVal dtMenuItems As Data.DataTable)
'recorremos cada elemento del datatable para poder determinar cuales son elementos hijos
'del menuitem dado pasado como parametro ByRef.
For Each drMenuItem As Data.DataRow In dtMenuItems.Rows
If drMenuItem("IdPadre").ToString.Equals(mnuMenuItem.Value) AndAlso _
Not drMenuItem("IdRecurso").Equals(drMenuItem("IdPadre")) Then
Dim mnuNewMenuItem As New MenuItem
mnuNewMenuItem.Value = drMenuItem("IdRecurso").ToString
mnuNewMenuItem.Text = drMenuItem("Menu").ToString
mnuNewMenuItem.ImageUrl = drMenuItem("Icono").ToString
mnuNewMenuItem.NavigateUrl = drMenuItem("Url").ToString

'Agregamos el Nuevo MenuItem al MenuItem que viene de un nivel superior.
mnuMenuItem.ChildItems.Add(mnuNewMenuItem)

'llamada recursiva para ver si el nuevo menú ítem aun tiene elementos hijos.
AddMenuItem(mnuNewMenuItem, dtMenuItems)
End If
Next

End Sub
End Class

A ver si les sirve todo esto, si olvidé algo me dicen por que estoy comenzando a hacer mis pininos en este asunto del Bloggeo.

Saludos Juanjo.

No hay comentarios: