Nuevo Menu dinámico enlazado a tabla SQL para ASP.net.

Que pasaría si necesitamos presentar en nuestra aplicación un menú diferente para cada perfil de usuario. O que la estructura del menú varíe de acuerdo al país desde donde se esta ingresando. O quizás, ambas cosas combinadas a la vez.
Hay muchísimos motivos por los cuales podemos necesitar reestructurar nuestro menú dinamicamente.
Una de las soluciones mas típicas es representarlo dentro de una o varias tablas SQL, para luego seleccionar los puntos del menú que puedan ser accedidos según criterio deseado y finalmente presentarlo en nuestra página.

Aquí les dejo una práctica solución que espero les sea útil en esta tarea.

El control esta pensado para adaptarse a cualquier estructura de tabla de menú, ya que posee las propiedades para mapear los campos necesarios. La única condición es que esta estructura sea perfectamente compatible con una estructura de árbol. Pudiendo ser de uno o mas niveles.

Los nodos serán obtenidos del servidor a través de un ProveedorDatosServidor y deberá contar con al menos los siguiente cuatro campos:

1. Identificación única del Nodo (generalmente ID).
2. Identificación de su Nodo Padre, coincidiendo con el ID de otro Nodo.
3. Descripción o etiqueta del Nodo.
4. URL con la dirección de la página que deseamos invocar cuando ese Nodo sea seleccionado.

Además los nodos deberán aparecer ordenados por su Nodo Padre, de tal manera que todos los nodos de un subnodo se vean juntos.

Veamos un ejemplo:

Teniendo la siguiente Tabla SQL que representa nuestro Menu:

Nodo NodoPadre Etiqueta URL PideClave
/5/ Raiz 0
/5/1/ /5/ Opcion Uno 0
/5/2/ /5/ Opcion Dos 0
/5/3/ /5/ Opcion Tres 0
/5/4/ /5/ Opcion Cuatro 0
/5/1/1/ /5/1/ Opcion Uno Uno /MiSistema/Opcion11.Aspx 0
/5/1/2/ /5/1/ Opcion Uno Dos /MiSistema/Opcion12.Aspx 0
/5/1/3/ /5/1/ Opcion Uno Tres /MiSistema/Opcion13.Aspx 0
/5/2/1/ /5/2/ Opcion Dos Uno /MiSistema/Opcion21.Aspx 1
/5/2/2/ /5/2/ Opcion Dos Dos /MiSistema/Opcion22.Aspx 0
/5/2/3/ /5/2/ Opcion Dos Tres /MiSistema/Opcion23.Aspx 1
/5/2/4/ /5/2/ Opcion Dos Cuatro /MiSistema/Opcion24.Aspx 0
/5/3/1/ /5/3/ Opcion Tres Uno 0
/5/3/2/ /5/3/ Opcion Tres Dos /MiSistema/Opcion32.Aspx 0
/5/3/3/ /5/3/ Opcion Tres Tres 0
/5/3/4/ /5/3/ Opcion Tres Cuatro /MiSistema/Opcion34.Aspx 0
/5/4/1/ /5/4/ Opcion Cuatro Uno /MiSistema/Opcion41.Aspx 0
/5/4/2/ /5/4/ Opcion Cuatro Dos /MiSistema/Opcion42.Aspx 0
/5/4/3/ /5/4/ Opcion Cuatro Tres /MiSistema/Opcion43.Aspx 0
/5/4/4/ /5/4/ Opcion Cuatro Cuatro /MiSistema/Opcion44.Aspx 0
/5/3/1/1/ /5/3/1/ Opcion Tres Uno Uno /MiSistema/Opcion311.Aspx 0
/5/3/1/2/ /5/3/1/ Opcion Tres Uno Dos /MiSistema/Opcion312.Aspx 1
/5/3/1/3/ /5/3/1/ Opcion Tres Uno Tres /MiSistema/Opcion313.Aspx 0
/5/3/3/1/ /5/3/3/ Opcion Tres Tres Uno /MiSistema/Opcion331.Aspx 0
/5/3/3/2/ /5/3/3/ Opcion Tres Tres Dos /MiSistema/Opcion332.Aspx 1
/5/3/3/3/ /5/3/3/ Opcion Tres Tres Tres /MiSistema/Opcion333.Aspx 0

Generaremos el siguiente código ASPX:

<body>
    <script type="text/javascript">
        function MenuSeleccionado(sender, e) {
            if (e.Registro.PideClave) {
                alert("Necesita permiso para esta opción")
                e.Cancelar = true;
            }
        }
    </script>
    <form id="form1" runat="server">
    <cc1:ScriptManager ID="ScriptManager1" runat="server">
    </cc1:ScriptManager>
    <cc1:ProveedorDatosServidor ID="DatosMenu" runat="server" WebMethod="ManejoMenu">
        <Ordenes>
            <cc1:OrdenDatos Columna="NodoPadre" />
        </Ordenes>
    </cc1:ProveedorDatosServidor>
    <cc1:Menu ID="MenuUno" runat="server" IdMenu="DatosMenu" CampoEtiqueta="Etiqueta"
        CampoPadre="NodoPadre" CampoId="Nodo" CampoURL="url" Seleccionando="MenuSeleccionado">
    </cc1:Menu>
   </form>
</body>

Antes de seguir les recomiendo vean este post si no recuerdan como usar el ProveedorDatosServidor para obtener datos de SQL.

Aquí vemos básicamente tres objetos:
1. El ScriptManager: Necesario ya que nuestro menú no es mas que un Panel que implementa la interfaz IScriptControl.
2. El ProveedorDatosServidor: nos permite contar con la tabla de menú en el cliente.
3. El control Menu: nos va a generar la representación visual de los datos obtenidos.

Vemos también una función en Javascript que será ejecutada cada vez que se seleccione un Nodo del menú.
A esta función llegan dos parámetros:
1. sender: es el control menú.
2. e: contiene el registro del ProveedorDatosServidor seleccionado y una propiedad llamada Cancelar que si es asignada en true, anula la seleccion.

Ahora paso a describir las propiedades de nuestro control:

Propiedad Tipo Descripción Defecto
IdMenu String Id del ProveedorDatosServidor del cual se obtendrán los nodos. String.Empty
CampoEtiqueta String Nombre de la columna en la tabla que queremos usar como descripción del Nodo. String.Empty
CampoId String Nombre de la columna en la tabla que queremos usar como identificador Nodo. String.Empty
CampoPadre String Nombre de la columna en la tabla que queremos usar como identificador del Nodo de nivel superior. String.Empty
CampoURL String Nombre de la columna en la tabla que queremos usar como dirección de página a la cual se invocará una vez seleccionado el Nodo. String.Empty
Seleccionando String Nombre de la función en Javascript que se ejecutará cuando un Nodo sea seleccionado. String.Empty

Si pudiéramos ver lo que genera nuestro control, aparecería algo así:

 <div id="MenuUno">
        <ul class="Menu">
            <li><a href="" class="Submenu"><b>Opcion Uno</b> </a>
                <ul>
                    <li><a href="/MiSistema/Opcion11.Aspx"><b>Opcion Uno Uno</b></a></li>
                    <li><a href="/MiSistema/Opcion12.Aspx"><b>Opcion Uno Dos</b></a></li>
                    <li><a href="/MiSistema/Opcion13.Aspx"><b>Opcion Uno Tres</b></a></li>
                </ul>
            </li>
            <li><a href="" class="Submenu"><b>Opcion Dos</b></a>
                <ul>
                    <li><a href="/MiSistema/Opcion21.Aspx"><b>Opcion Dos Uno</b></a></li>
                    <li><a href="/MiSistema/Opcion22.Aspx"><b>Opcion Dos Dos</b></a></li>
                    <li><a href="/MiSistema/Opcion23.Aspx"><b>Opcion Dos Tres</b></a></li>
                    <li><a href="/MiSistema/Opcion24.Aspx"><b>Opcion Dos Cuatro</b></a></li>
                </ul>
            </li>
            <li><a href="" class="Submenu"><b>Opcion Tres</b></a>
                <ul>
                    <li><a href="" class="Submenu"><b>Opcion Tres Uno</b></a>
                        <ul>
                            <li><a href="/MiSistema/Opcion311.Aspx"><b>Opcion Tres Uno Uno</b></a></li>
                            <li><a href="/MiSistema/Opcion312.Aspx"><b>Opcion Tres Uno Dos</b></a></li>
                            <li><a href="/MiSistema/Opcion313.Aspx"><b>Opcion Tres Uno Tres</b></a></li>
                        </ul>
                    </li>
                    <li><a href="/MiSistema/Opcion32.Aspx"><b>Opcion Tres Dos</b></a></li>
                    <li><a href="" class="Submenu"><b>Opcion Tres Tres </b></a>
                        <ul>
                            <li><a href="/MiSistema/Opcion331.Aspx"><b>Opcion Tres Tres Uno</b></a></li>
                            <li><a href="/MiSistema/Opcion332.Aspx"><b>Opcion Tres Tres Dos</b></a></li>
                            <li><a href="/MiSistema/Opcion333.Aspx"><b>Opcion Tres Tres Tres</b></a></li>
                        </ul>
                    </li>
                    <li><a href="/MiSistema/Opcion34.Aspx"><b>Opcion Tres Cuatro</b></a></li>
                </ul>
            </li>
            <li><a href="" class="Submenu"><b>Opcion Cuatro</b></a>
                <ul>
                    <li><a href="/MiSistema/Opcion41.Aspx"><b>Opcion Cuatro Uno</b></a></li>
                    <li><a href="/MiSistema/Opcion42.Aspx"><b>Opcion Cuatro Dos</b></a></li>
                    <li><a href="/MiSistema/Opcion43.Aspx"><b>Opcion Cuatro Tres</b></a></li>
                    <li><a href="/MiSistema/Opcion44.Aspx"><b>Opcion Cuatro Cuatro</b></a></li>
                </ul>
            </li>
        </ul>
    </div>

Como vemos el objeto creado es bastante primitivo. Si bien funciona perfectamente, su apariencia deja mucho que desear.
Aquí es donde entra en juego nuestra habilidad para dar un aspecto agradable a través de los StyleSheet.
Por si están con pocas ganas de hacerlo o, su capacidad para combinar colores es tan pobre como la mía, les dejo uno estilo armado a modo de ejemplo para que rápidamente puedan ver el resultado final.

#MenuUno {}
#MenuUno .Menu { float  :left; padding:0; margin:3px 0 0 0; list-style:none; position:relative; width:130px;}
#MenuUno .Menu ul {padding:0; margin:0; list-style:none; width:130px; height:auto; position:absolute; left:-9999px; top:0;}

#MenuUno .Menu li { list-style-type :none;  list-style-image :none; float:left; margin-bottom:1px;}
#MenuUno .Menu li a{display: block;float: left;width: 200px;height: 24px;background: #888;color: #000;line-height: 24px;font-family: arial, sans-serif;font-size: 11px;text-decoration: none;text-indent: 10px;border-right: solid medium #FF9933;}
#MenuUno .Menu li a.Submenu{}
#MenuUno .Menu li:hover {position:relative;}
#MenuUno .Menu li a:hover {position:relative}

#MenuUno .Menu ul li a {background:#aaa;}
#MenuUno .Menu ul li a.Submenu {}
#MenuUno .Menu ul ul li a {background:#ccc;}
#MenuUno .Menu ul ul li a.Submenu {}
#MenuUno .Menu ul ul ul li a {background:#eee;}
#MenuUno .Menu ul ul ul li a.Submenu {}

#MenuUno .Menu :hover ul,
#MenuUno .Menu :hover ul :hover ul,
#MenuUno .Menu :hover ul :hover ul :hover ul {left:203px;}

#MenuUno .Menu :hover ul ul,
#MenuUno .Menu :hover ul :hover ul ul {left:-9999px;}

#MenuUno .Menu li:hover > a {background-color:#e60; color:#fff;}
#MenuUno .Menu ul li:hover > a {background-color:#e60; color:#fff;}
#MenuUno .Menu ul ul li:hover > a {background-color:#e60; color:#fff;}

El Menú debería quedar así:

Aquí va otro ejemplo que usa CSS3 y ademas implementa un control de usuario para loguearse al sistema. Les recomiendo lo vean con Chrome, FireFox o Explorer 10.

Esta es una de las múltiples formas que puede tomar nuestro menú. Si quieren ver unas cuantas muy buenas les recomiendo esta página, donde se van a poder bajar estilos que, con unas pocas modificaciones, podrán adaptarse a nuestro menú perfectamente.

Si les interesa ver el funcionamiento en vivo o bajarse el proyecto con todas las demostraciones, pueden hacerlo desde el panel de le derecha de este blog.
Y como siempre aquí les dejo la Librería MoniMisi2 para que se bajen con este control y todo lo desarrollado hasta ahora.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s