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.

miércoles, 10 de septiembre de 2008

Buscar item gridview

Esta entrada es a petición de mi buen amigo Juan José Mendez de Guatemala, así que espero que le sirva a él y aquien se le ofrezca realizar esto:

Primero que nada insertaremos un gridview de la siguiente manera:


Este gridview está ligado a una fuente de datos, representada de la siguiente manera:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource1">
<Columns>
<asp:BoundField DataField="IdEmpleado" HeaderText="IdEmpleado" InsertVisible="False" ReadOnly="True" SortExpression="IdEmpleado" />
<asp:BoundField DataField="NombreEmpleado" HeaderText="NombreEmpleado"
SortExpression="NombreEmpleado" />
<asp:BoundField DataField="FechaAlta" HeaderText="FechaAlta"
SortExpression="FechaAlta" />
<asp:CheckBoxField DataField="IdEstatusEmpleado" HeaderText="IdEstatusEmpleado"
SortExpression="IdEstatusEmpleado" />
</Columns>
</asp:GridView>

Si visualizamos la consulta, contiene un LIKE y el parámetro por default de entrada es un simbolo de %, el cual nos muestra todo los empleados.
Ahora este parámetro depende de un control TextBox1, en el cual vamos introducir nuestra consulta, y colocaremos un botón para actualizar nuestro gridview, estos controles los pondremos en la parte superior de le siguiente manera:
<asp:Label ID="Label1" runat="server" Text="Filtrar Nombre:"></asp:Label>
&nbsp;<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
&nbsp;<asp:Button ID="Button1" runat="server" Text="Filtrar" />

Y de esta manera localizaremos un elemento o los elementos que coincidan con parte de nuestra consulta.



Ahora si solamente necesitamos que al realizar la busqueda se marquen o se cambien de color los renglon(es) encontrado(s), entonces debemos hechar mano de algo de código.

Primero debemos dar doble click sobre el botón filtrar para que se cree el evento click en el cual agregaremos el siguiente código quedando así:

protected void Button1_Click(object sender, EventArgs e)
{
foreach(GridViewRow Row in GridView1.Rows)
{
if (Row.Cells[1].Text.Contains(TextBox1.Text))
{
Row.BackColor = System.Drawing.Color.Coral;
}
}
}

Este código lo que hace es al dar click en el boton filtrar, es recorrer cada uno de los renglones del gridview en cuestión, y buscar que en la celda 1 que es la que tiene el nombre del empleado contenga el texto de nuestra busqueda, si la encuentra lo que hace es cambiar de color el renglón.

También hay que recordar que nuestro DataSource debe cambiar por que ya no se realizará el filtrado en directamente a la base de datos, sino simplemente marcaremos en nuestros gridview nuestra busqueda quedando así:

<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT * FROM Gen_TEmpleado WHERE NombreEmpleado LIKE '%' + @p_NombreEmpleado + '%'">
<SelectParameters>
<asp:Parameter Name="p_NombreEmpleado" DefaultValue="%" />
</SelectParameters>
</asp:SqlDataSource>


A Continuación muestro como se vería nuestro resultado de la busqueda utilizando el nombre Carlos.




Bueno Juanjo, espero te sirva, si tuvieras mas dudas me dices. Saludos a todos y que sea de mucha utilidad todo esto.

martes, 2 de septiembre de 2008

Pool Applications folder & Server Application Unavailable

Pues siguiendo el consejo que encontré en uno de los tantos Blogs, redacto esta entrada, ya que ahi recomendaban utilizar el blog como un historial o bitácora de los problemas que he podido resolver, y aquí les dejo una ayuda por si la ocupan en algún momento(Un buen consejo).

Llegue con un cliente queriendo realizar unas modificaciones a una aplicación Web un poco antigua (asp 3.0), y pues ya todos mis desarrollos son AS.NET con FrameWork 2.0 y 3.5, así que me dispuse a colocar las modificaciones en la misma aplicación y para mi sorpresa solo pude obtener el error "Server Application Uavailable", me cansé de googlear encontrando información que debería de cambiar el usuario, darle permisos, instalé y desinstalé el framework etc... ya casi estaba apunto de desintarlar el IIS, pero recordé que al comienzo de mi googleada, había encontrado información sobre los Application Pools.
El problema fue que en mi Windows 2003 standard no estaba esa carpeta de la que hablaban todos los artículos que encontré, así que encontré otro artículo en donde indica la razón de por que esa carpetita no aparece y lo que ocurre es que en ocasiones al configurar el IIS 6.0, se marcar la opción de que corra de forma como lo hacia IIS 5.0. En donde todos los procesos o aplicaciones corrian bajo el mismo pool, el problema era que si una aplicación hacia que el IIS 5.0 se congelara u ocurriera algun otro error todas las aplicaciones bajo ese IIS se detenían también.
Así que para poder ver la carpeta de los Applications Pools hay que hacer lo siguiente:
  1. En el IIS Manager, expande el nombre de la computadora local, da clic derecho sobre Web Sites, y seleccionar propiedades.
  2. Clic en el tab de Service, y deseleccionar la casilla Run WWW service in IIS 5.0 isolation mode, y damos OK.
  3. Para reinicar nuevamente el WWW service, hay que confirmar que si cuando se pregunte que queremos reiniciar el IIS ahora.

Aquí les dejo el post original de como aparecer el Folder Application Pools

Después de haber configurado como debe ser el IIS 6.0 ahora si podemos pasar a configurar nuestro Application Pool para FrameWork 2.0, haciendo lo siguiente:

  1. Extendemos la nueva carpeta de Application Pools, damos clic derecho sobre esa carpeta y le decimos New Application Pool.
  2. En la ventana le colocamos el nombre que nosotros queramos indicarle al nuevo Pool en mi caso NetFrameWork2Pool, dejamos la opción de utilizar la configuración por default.
  3. Ahora nos vamos a nuestro directorio virtual o application Web y entonces enla opción del Pool que vamos a ocupar seleccionamos el nuevo.
  4. Y listo a disfrutar de sus modificaciones.

Les dejo la referencia con imagenes de como configurar el Application Pool

También un poco mas de explicación sobre el por que el IIS 6.0 de repetente ese encuentra configurado para que corra en Isolation Mode Por que descrubrí que también surge después de una actualización de II5 a II6 o de Windows 2000 a Windows 2003.