Mostrando las entradas con la etiqueta Web Control. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Web Control. Mostrar todas las entradas

jueves, 14 de agosto de 2014

El Demo del Día: Plantilla Jerárquica con el Control Web Repeater

Plantilla Jerárquica con el Control Web Repeater

Requerimiento

Se desea mostrar una consulta jerárquica de productos por categoría en una grilla en ASP .NET. La consulta debe ser desconectada.

Solución

No existe un control Jerárquico que muestre varias columnas tipo TreeGrid. El control TreeView muestra solo un nodo y el control GridView no soporta jerarquía.
La solución es usar plantillas jerárquicas en cualquiera de los controles enlazados a datos: GridView, DataList o Repeater.
Nosotros elegimos el Repeater y crearemos una plantilla jerárquica, es decir un control Repeater con otro control Repeater dentro.

Nota: En este caso quitaremos el ViewState en los dos controles Repeater para disminuir el HTML enviado al cliente ya que los filtros se harán en el servidor pero se mostraran en el cliente con Javascript.

Crear el Procedimiento Almacenado en la Base de Datos de SQL Server

Create Procedure [dbo].[uspCategoriesProductsListar]
As
Select CategoryID,CategoryName From Categories
Select ProductID,ProductName,SupplierID,CategoryID,UnitPrice,UnitsInStock From Products

Crear una Librería de Clases con las Entidades del Negocio

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.EntidadesNegocio" y modificar el código de la clase como sigue:

using System;
namespace Northwind.Librerias.EntidadesNegocio
{
    public class beCategoria
    {
        public int IdCategoria { get; set; }
        public string Nombre { get; set; }
    }
}

Agregar una nueva clase al proyecto y llamarla "beProducto":

using System;
namespace Northwind.Librerias.EntidadesNegocio
{
    public class beProducto
    {
        public int IdProducto { get; set; }
        public string Nombre { get; set; }
        public int IdProveedor { get; set; }
        public int IdCategoria { get; set; }
        public decimal PrecioUnitario { get; set; }
        public short Stock { get; set; }
    }
}

Agregar otra clase al proyecto y llamarla "beCategoriaProducto":

using System;
using System.Collections.Generic;
namespace Northwind.Librerias.EntidadesNegocio
{
    public class beCategoriaProducto
    {
        public List<beCategoria> ListaCategorias { get; set; }
        public List<beProducto> ListaProductos { get; set; }
    }
}

Crear una Librería de Acceso a Datos

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.AccesoDatos", primero hacer una referencia a la Librería de Entidades del Negocio y luego modificar el código de la clase como sigue:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Northwind.Librerias.EntidadesNegocio;

namespace Northwind.Librerias.AccesoDatos
{
    public class daCategoriaProducto
    {
        public beCategoriaProducto obtenerListas(SqlConnection con)
        {
            beCategoriaProducto obeCategoriaProducto = new beCategoriaProducto();
            List<beCategoria> lbeCategoria = null;
            List<beProducto> lbeProducto = null;

            SqlCommand cmd = new SqlCommand("uspCategoriesProductsListar", con);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlDataReader drd = cmd.ExecuteReader(); //Varios Selects
            if (drd != null)
            {
                //Llenar las Categorias
                lbeCategoria = new List<beCategoria>();
                int posIdCat = drd.GetOrdinal("CategoryID");
                int posNomCat = drd.GetOrdinal("CategoryName");
                beCategoria obeCategoria;
                while (drd.Read())
                {
                    obeCategoria = new beCategoria();
                    obeCategoria.IdCategoria = drd.GetInt32(posIdCat);
                    obeCategoria.Nombre = drd.GetString(posNomCat);
                    lbeCategoria.Add(obeCategoria);
                }
                //Avanzar al siguiente Select
                if (drd.NextResult())
                {
                    //Llenar los Productos
                    lbeProducto = new List<beProducto>();
                    int posIdProducto = drd.GetOrdinal("ProductID");
                    int posNombre = drd.GetOrdinal("ProductName");
                    int posIdProveedor = drd.GetOrdinal("SupplierID");
                    int posIdCategoria = drd.GetOrdinal("CategoryID");
                    int posPrecioUnitario = drd.GetOrdinal("UnitPrice");
                    int posStock = drd.GetOrdinal("UnitsInStock");
                    beProducto obeProducto;
                    while (drd.Read())
                    {
                        obeProducto = new beProducto();
                        obeProducto.IdProducto = drd.GetInt32(posIdProducto);
                        obeProducto.Nombre = drd.GetString(posNombre);
                        obeProducto.IdProveedor = drd.GetInt32(posIdProveedor);
                        obeProducto.IdCategoria = drd.GetInt32(posIdCategoria);
                        obeProducto.PrecioUnitario = drd.GetDecimal(posPrecioUnitario);
                        obeProducto.Stock = drd.GetInt16(posStock);
                        lbeProducto.Add(obeProducto);
                    }
                }
                drd.Close();
                obeCategoriaProducto.ListaCategorias = lbeCategoria;
                obeCategoriaProducto.ListaProductos = lbeProducto;
            }
            return (obeCategoriaProducto);
        }
    }
}

Crear una Librería de Reglas del Negocio

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.ReglasNegocio", hacer una referencia a la Librería de Entidades del Negocio, a la Librería de Acceso a Datos y a System.Configuration y luego modificar el código de la clase como sigue:

using System;
using System.Configuration; //ConfigurationManager
namespace Northwind.Librerias.ReglasNegocio
{
    public class brGeneral
    {
        //Propiedad
        public string Conexion { get; set; }

        //Constructor
        public brGeneral()
        {
            Conexion = ConfigurationManager.ConnectionStrings["conNW"].ConnectionString;
        }
    }
}

Agregar otra clase llamada: "brCategoriaProducto:" y escribir el siguiente código:

using System;
using System.Collections.Generic; //List
using System.Data.SqlClient; //SqlConnection
using Northwind.Librerias.EntidadesNegocio; //beCategoriaProducto
using Northwind.Librerias.AccesoDatos; //daCategoriaProducto

namespace Northwind.Librerias.ReglasNegocio
{
    public class brCategoriaProducto:brGeneral
    {
        public beCategoriaProducto obtenerListas()
        {
            beCategoriaProducto obeCategoriaProducto = null;
            using (SqlConnection con = new SqlConnection(Conexion))
            {
                try
                {
                    con.Open();
                    daCategoriaProducto odaCategoriaProducto = new daCategoriaProducto();
                    obeCategoriaProducto = odaCategoriaProducto.obtenerListas(con);
                }
                catch (SqlException ex)
                {
                    //Capturar el error y grabar un Log
                }
            } //con.Close(); con.Dispose(); con = null;
            return (obeCategoriaProducto);
        }
    }
}

Nota: La clase "brCategoriaProducto" hereda de la clase "brGeneral" la cadena de conexión para no pasarla como parámetro en cada método de la clase o en el constructor de cada clase se hace una sola vez.

Crear la Aplicación Web en ASP .NET Web Form

Crear un "Nuevo Sitio web vacío de ASP .NET" en C# llamado "Demo15" y crear las siguientes carpetas:
- Estilos: Para el archivo de hoja de estilo (CSS).
- Imagenes: Conteniendo 2 archivos: Contraer.png y Expandir.png
- Paginas: Para contener la pagina de lista de empleados.

Crear el Archivo de Hoja de Estilo (CSS)

Seleccionar la carpeta "Estilos" y agregar un archivo de hoja de estilos con el nombre de: "ACME.css" y modificar el código como sigue:

body {
    background-color:aqua;
}
.Titulo {
    background-color:black;
    color:white;
    text-transform:uppercase;
    font-size:xx-large;
    font-weight:bold;
}
.Subtitulo {
    background-color:white;
    color:blue;
    text-transform:capitalize;
    font-size:x-large;
    font-weight:bold;
}

Crear la Pagina ASP .NET como un Formulario Web Form

Seleccionar la carpeta "Paginas" y agregar un Formulario Web Form llamado: "CategoriaProductos.aspx", para empezar a diseñar la pagina hay que hacer referencia a las Librerías de Negocio (que copia todas sus dependencias).

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="CategoriaProductos.aspx.cs" Inherits="Paginas_CategoriaProducto" %>
<%@ Import Namespace="Northwind.Librerias.EntidadesNegocio" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link href="../Estilos/ACME.css" rel="stylesheet" type="text/css" />
    <script>
        function mostrarProductos(img, indice) {
            var fila = document.getElementById("fila" + indice);
            if (img.title == "Expandir") {
                fila.style.display = "table-row";
                img.src = "../Imagenes/Contraer.png";
                img.title = "Contraer";
            }
            else {
                fila.style.display = "none";
                img.src = "../Imagenes/Expandir.png";
                img.title = "Expandir";
            }
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table style="width:100%">
            <tr>
                <td class="Titulo">Plantillas Jerarquicas en el Repeater</td>
            </tr>
            <tr>
                <td class="Subtitulo">Consulta de Productos x Categoria</td>
            </tr>
            <tr>
                <td>
                    <asp:Repeater ID="rpCategoria" EnableViewState="false" runat="server">
                        <HeaderTemplate>
                            <table style="width:100%">
                                <tr style="background-color:blue;color:white">
                                    <td style="width:10%">Código</td>
                                    <td style="width:90%">Nombre de la Categoria</td>
                                </tr>
                        </HeaderTemplate>
                        <ItemTemplate>
                            <tr style="background-color:white;color:blue">
                                <td>
                                    <img id="imgSimbolo" alt="" title="Expandir"
                                       src="../Imagenes/Expandir.png"
                                        width="20" height="20" style="cursor:pointer"
                                        onclick="mostrarProductos(this,<%#Container.ItemIndex%>);"/>
                                    &nbsp;&nbsp;
                                    <%#((beCategoria)Container.DataItem).IdCategoria%>
                                </td>
                                <td>
                                    <%#((beCategoria)Container.DataItem).Nombre%>
                                </td>
                            </tr>
                            <tr id="fila<%#Container.ItemIndex%>" style="display:none">
                                <td></td>
                                <td>
                                    <asp:Repeater ID="rpProducto" DataSource="<%#filtrarProductos
                                      (((beCategoria)Container.DataItem).IdCategoria)%>"
                                      EnableViewState="false" runat="server">
                                         <HeaderTemplate>
                                            <table style="width:100%">
                                                <tr style="background-color:red;color:white">
                                                    <td style="width:20%">Código</td>
                                                    <td style="width:40%">Nombre del Producto</td>
                                                    <td style="width:20%">Precio</td>
                                                    <td style="width:20%">Stock</td>
                                                </tr>
                                        </HeaderTemplate>
                                        <ItemTemplate>
                                            <tr style="background-color:white;color:red">
                                                <td><%#((beProducto)Container.DataItem).IdProducto%></td>
                                                <td><%#((beProducto)Container.DataItem).Nombre%></td>
                                                <td><%#((beProducto)Container.DataItem).
                                                          PrecioUnitario.ToString("n2")%></td>
                                                <td><%#((beProducto)Container.DataItem).Stock%></td>
                                            </tr>
                                        </ItemTemplate>
                                        <FooterTemplate>
                                            </table>
                                        </FooterTemplate>
                                    </asp:Repeater>
                                </td>
                            </tr>
                        </ItemTemplate>
                        <FooterTemplate>
                            </table>
                        </FooterTemplate>
                    </asp:Repeater>
                </td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>

Nota: Inicialmente los controles Repeaters de productos creados por cada categoría están ocultos (display:none), pero por código Javascript lo mostramos usando: display:"table-row". No usamos display:inline ya que no se vería bien en algunos navegadores, en cambio, usando "table-row" se muestra sin problemas en todos los navegadores.

El diseño de la pagina se mostrará como en la siguiente figura:


Escribir el siguiente código C# en la página:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Northwind.Librerias.EntidadesNegocio;
using Northwind.Librerias.ReglasNegocio;

public partial class Paginas_CategoriaProducto : System.Web.UI.Page
{
    private List<beProducto> lbeProducto;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            brCategoriaProducto obrCategoriaProducto = new brCategoriaProducto();
            beCategoriaProducto obeCategoriaProducto = obrCategoriaProducto.obtenerListas();
            lbeProducto = obeCategoriaProducto.ListaProductos;
            rpCategoria.DataSource = obeCategoriaProducto.ListaCategorias;
            rpCategoria.DataBind();
        }
    }

    protected List<beProducto> filtrarProductos(int idCategoria)
    {
        return (lbeProducto.FindAll(x => x.IdCategoria.Equals(idCategoria)));
    }
}

Nota: En el evento load se carga las 2 listas de categorías y productos, luego se enlaza las categorías al primer control Repeater y el segundo se enlaza a una función "filtrarProductos" que solo selecciona las productos de cada categoría.

Modificar el Archivo Web.Config para especificar la cadena de conexión a Northwind

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="conNW" providerName="SQLServer" connectionString="uid=UsuarioNW;pwd=123456;
      data source=DSOFT\Sqlexpress; database=Northwind"/>
  </connectionStrings>
    <system.web>
      <compilation debug="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" />
    </system.web>
</configuration>

Probar la Pagina Web

Guardar el Sitio Web, clic derecho a la Pagina "CategoriaProductos.aspx" y seleccionar "Ver en el explorador".


Desplegar cada código de categoría dando clic a la imagen de Expandir (+) y se mostrarán los productos de dicha categoría y para ocultarla usar la imagen de Contraer (-).

Comentario Final

En este post hemos visto como crear una presentación jerárquica usando plantillas en el control Repeater. Hemos trabajado solo con 2 niveles pero podría ser de varios niveles. Como comentario final, si aprendemos bien a usar plantillas de datos (Data Templates) en cualquier control web (enlazado a datos) podemos darle la apariencia que deseemos, sin necesidad de tener un control especifico para cada funcionalidad.

Espero les sirva y será hasta la siguiente semana que veremos como trabajar con el GridView: Paginar, Ordenar, Filtrar en las cabeceras, Pies, etc.

Descarga:
Demo15_Plantilla_Jerarquica_Repeater




miércoles, 6 de agosto de 2014

El Demo del Día: Paginar, Ordenar y Filtrar en el Control Web DataList

Paginar, Ordenar y Filtrar en el Control Web DataList

Requerimientos

Se desea crear una Aplicación Web que permita listar los datos de los empleados que cumpla con lo siguiente:
- Presente en forma de ficha la información del código, apellido, nombre y fecha de nacimiento del empleado.
- Muestre en la ficha la foto del empleado la cual se encuentra en un carpeta "Empleados" donde el nombre del archivo esta compuesto por el código del empleado y la extensión jpg. Para los archivos que no se encuentren se usará el archivo No.jpg.
- Las fichas deben tener fondo gris claro, pero al pasar el mouse el estilo de la ficha cambiara a fondo amarillo.
- La información debe estar paginada (por defecto mostrar 6 registros de empleados), mediante botones de desplazamiento y enlaces con números de paginas.
- Se debe permitir ordenar los registros por cualquier campo en forma ascendente y descendente.
- Se debe permitir filtrar los registros por cualquier campo ingresando el dato buscado.

Solución

Usaremos el control DataList con Plantilla de Datos para poder presentar en forma de ficha la información del empleado y mostrarla en varias columnas. Ademas agregaremos botones y enlaces para paginar, combos para seleccionar los criterios de ordenación y filtro de registros.

Nota: En este caso si podemos deshabilitar el ViewState del DataList ya que no hay ningun control dentro de la plantilla que haga PostBack, es decir enviaremos el minimo HTML al navegador en el cliente.

Crear el Procedimiento Almacenado en la Base de Datos de SQL Server

Usaremos la tabla Empleados (Employees) de Northwind:

Create Procedure [dbo].[uspEmployeesListar]
As
Select EmployeeID,LastName,FirstName,
IsNull(BirthDate,'1/1/1900') As BirthDate
From Employees Order By 1

Crear una Librería de Clases con las Entidades del Negocio

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.EntidadesNegocio" y modificar el código de la clase como sigue:

using System;
namespace Northwind.Librerias.EntidadesNegocio
{
    public class beEmpleado
    {
        public int IdEmpleado { get; set; }
        public string Apellido { get; set; }
        public string Nombre { get; set; }
        public string NombreCompleto
        {
            get
            {
                return (String.Format("{0} {1}",Nombre,Apellido));
            }
        }
        public DateTime FechaNacimiento { get; set; }
    }
}

Crear una Librería de Acceso a Datos

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.AccesoDatos" y modificar el código de la clase como sigue:

using System;
using System.Data; //CommandType
using System.Data.SqlClient; //SqlConnection, SqlCommand, SqlDataReader
using System.Collections.Generic; //List
using Northwind.Librerias.EntidadesNegocio; //beEmpleado
namespace Northwind.Librerias.AccesoDatos
{
    public class daEmpleado
    {
        public List<beEmpleado> listar(SqlConnection con)
        {
            List<beEmpleado> lbeEmpleado = null;
            SqlCommand cmd = new SqlCommand("uspEmployeesListar", con);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlDataReader drd = cmd.ExecuteReader(CommandBehavior.SingleResult);
            if (drd != null)
            {
                lbeEmpleado = new List<beEmpleado>();
                int posIdEmpleado = drd.GetOrdinal("EmployeeID");
                int posApellido = drd.GetOrdinal("LastName");
                int posNombre = drd.GetOrdinal("FirstName");
                int posFechaNacimiento = drd.GetOrdinal("BirthDate");
                beEmpleado obeEmpleado;
                while (drd.Read())
                {
                    obeEmpleado = new beEmpleado();
                    obeEmpleado.IdEmpleado = drd.GetInt32(posIdEmpleado);
                    obeEmpleado.Apellido = drd.GetString(posApellido);
                    obeEmpleado.Nombre = drd.GetString(posNombre);
                    obeEmpleado.FechaNacimiento = drd.GetDateTime(posFechaNacimiento);
                    lbeEmpleado.Add(obeEmpleado);
                }
                drd.Close();
            }
            return (lbeEmpleado);
        }
    }
}

Nota: Hay que hacer una referencia a la Librería de Entidades del Negocio.

Crear una Librería de Reglas del Negocio

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.ReglasNegocio" y modificar el código de la clase como sigue:

using System;
using System.Configuration; //ConfigurationManager
namespace Northwind.Librerias.ReglasNegocio
{
    public class brGeneral
    {
        //Propiedad
        public string Conexion { get; set; }

        //Constructor
        public brGeneral()
        {
            Conexion = ConfigurationManager.ConnectionStrings["conNW"].ConnectionString;
        }
    }
}

Nota: Hay que hacer una referencia a la Librería de Entidades del Negocio, a la Librería de Acceso a Datos y a System.Configuration.

Agregar otra clase llamada: "brEmpleado" y escribir el siguiente código:

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using Northwind.Librerias.EntidadesNegocio;
using Northwind.Librerias.AccesoDatos;

namespace Northwind.Librerias.ReglasNegocio
{
    public class brEmpleado:brGeneral //Herencia
    {
        public List<beEmpleado> listar()
        {
            List<beEmpleado> lbeEmpleado = null;
            using (SqlConnection con = new SqlConnection(Conexion))
            {
                try
                {
                    con.Open();
                    daEmpleado odaEmpleado = new daEmpleado();
                    lbeEmpleado = odaEmpleado.listar(con);
                }
                catch (SqlException ex)
                {
                    //Capturar el error y grabar un Log
                }
            } //con.Close(); con.Dispose(); con = null;
            return (lbeEmpleado);
        }
    }
}

Nota: La clase "brEmpleado" hereda de la clase "brGeneral" la cadena de conexión para no pasarla como parámetro en cada método de la clase o en el constructor de cada clase se hace una sola vez.

Crear una Librería de Código de Usuario para Web

Crear un proyecto de tipo Librería de Clases en C# llamado: "General.Librerias.CodigoUsuarioWeb" y modificar el código de la clase como sigue:

using System;
using System.Collections.Generic;
using System.IO; //File
using System.Web; //HttpContext

namespace General.Librerias.CodigoUsuarioWeb
{
    public class Imagen
    {
        public static string obtenerUrl(int id, string carpeta)
        {
            string archivo = HttpContext.Current.Server.MapPath
            (String.Format("../Imagenes/{0}/{1}.jpg", carpeta, id));
            string url = String.Format("../Imagenes/{0}/{1}.jpg", carpeta, id);
            if (!File.Exists(archivo)) url = String.Format("../Imagenes/{0}/No.jpg", carpeta);
            return (url);
        }
    }
}

Nota: Como esta librería va a ser usada por paginas web hay que hacer referencia a: "System.Web"

Crear la Aplicación Web en ASP .NET Web Form

Crear un "Nuevo Sitio web vacío de ASP .NET" en C# llamado "Demo14" y crear las siguientes carpetas:
- Estilos: Para el archivo de hoja de estilo (CSS).
- Imagenes. Dentro crear otra carpeta llamada "Empleados" y adjuntar los archivos con las fotos de los empleados: 1.jpg, 2.jpg, 3.jpg, ... y No.jpg.
- Paginas: Para contener la pagina de lista de empleados.

Crear el Archivo de Hoja de Estilo (CSS)

Seleccionar la carpeta "Estilos" y agregar un archivo de hoja de estilos con el nombre de: "ACME.css" y modificar el código como sigue:

body {
    background-color:aqua;
}
.Titulo {
    background-color:black;
    color:white;
    text-transform:uppercase;
    font-size:xx-large;
    font-weight:bold;
}
.Subtitulo {
    background-color:white;
    color:blue;
    text-transform:capitalize;
    font-size:x-large;
    font-weight:bold;
}
.MarcarTabla {
    background-color: lightgray;
    cursor:default;
    border:solid;
    border-color:lightgray;
}
.MarcarTabla:hover {
    background-color: yellow;
    cursor:pointer;
    border:solid;
    border-color:black;
}

Crear la Pagina ASP .NET como un Formulario Web Form

Seleccionar la carpeta "Paginas" y agregar un Formulario Web Form llamado: "ListaEmpleados.aspx", para empezar a diseñar la pagina hay que hacer referencia a las Librerías de Negocio (que copia todas sus dependencias) y la Librería de Código de Usuario Web.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ListaEmpleados.aspx.cs" Inherits="Paginas_ListaEmpleados" %>
<%@ Import Namespace="Northwind.Librerias.EntidadesNegocio" %>
<%@ Import Namespace="General.Librerias.CodigoUsuarioWeb" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link href="../Estilos/ACME.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table style="width:100%">
            <tr>
                <td class="Titulo" colspan="5">Paginar, Ordenar y Filtrar en el DataList</td>
            </tr>
            <tr>
                <td class="Subtitulo" colspan="5">Lista de Empleados</td>
            </tr>
            <tr>
                <td style="width:10%">Ordenar Por: </td>
                <td style="width:20%">
                    <asp:DropDownList ID="ddlCampo" runat="server" />
                </td>
                <td style="width:10%">Tipo Orden: </td>
                <td style="width:20%">
                    <asp:DropDownList ID="ddlOrden" runat="server">
                        <asp:ListItem Value="0">Ascendente</asp:ListItem>
                        <asp:ListItem Value="1">Descendente</asp:ListItem>
                    </asp:DropDownList>
                </td>
                <td style="width:40%">
                    <asp:Button ID="btnOrdenar" Text="Ordenar" 
                      OnClick="ordenarCampo" runat="server"/>
                </td>
            </tr>
            <tr>
                <td style="width:10%">Filtrar Por: </td>
                <td style="width:20%">
                    <asp:DropDownList ID="ddlCriterio" runat="server" AutoPostBack="True" 
                      OnSelectedIndexChanged="cambiarControlBusqueda" />
                </td>
                <td style="width:10%">Dato Filtrar: </td>
                <td style="width:20%">
                    <asp:TextBox ID="txtDato" Width="130" runat="server" />
                </td>
                <td style="width:40%">
                    <asp:Button ID="btnFiltrar" Text="Filtrar" OnClick="filtrarCriterio" runat="server"/>
                </td>
            </tr>
            <tr>
                <td colspan="5" class="Subtitulo">Registros encontrados: 
                    <asp:Label ID="lblRegistros" Text="0" runat="server"/>
                </td>
            </tr>
            <tr>
                <td colspan="5">
                    <asp:DataList ID="dlsEmpleado" runat="server" EnableViewState="False" 
                        RepeatColumns="3" CellPadding="15" CellSpacing="15"
                        RepeatDirection="Horizontal">
                        <ItemTemplate>
                            <table class="MarcarTabla">
                                <tr>
                                    <td>
                                        <table>
                                            <tr>
                                                <td style="width:80px">Código :</td>
                                                <td style="width:100px">
                                                    <%#((beEmpleado)Container.DataItem).IdEmpleado%>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td style="width:80px">Apellido :</td>
                                                <td style="width:100px">
                                                    <%#((beEmpleado)Container.DataItem).Apellido%>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td style="width:80px">Nombre :</td>
                                                <td style="width:100px">
                                                    <%#((beEmpleado)Container.DataItem).Nombre%>
                                                </td>
                                            </tr>
                                            <tr>
                                                <td style="width:80px">Fecha Nac :</td>
                                                <td style="width:100px">
                                                    <%#((beEmpleado)Container.DataItem).FechaNacimiento.
                                                       ToShortDateString()%>
                                                </td>
                                            </tr>
                                        </table>
                                    </td>
                                    <td>
                                        <img src='<%#Imagen.obtenerUrl(((beEmpleado)Container.DataItem).
                                          IdEmpleado,"Empleados")%>' width="120" height="80" alt="Foto" 
                                          title="<%#((beEmpleado)Container.DataItem).NombreCompleto%>"/>
                                    </td>
                                </tr>
                            </table>
                        </ItemTemplate>
                   </asp:DataList>
                </td>
            </tr>
            <tr>
                <td id="celdaBotones" style="text-align:center" colspan="5" runat="server">
                    <asp:Button ID="btnPrimero" Text="<<" Width="50" 
                      runat="server" OnClick="btnPrimero_Click" />
                    <asp:Button ID="btnAnterior" Text="<" Width="50" 
                      runat="server" OnClick="btnAnterior_Click" />
                    <asp:TextBox ID="txtPosicion" Width="100" ReadOnly="true" runat="server" />
                    <asp:Button ID="btnSiguiente" Text=">" Width="50" 
                      runat="server" OnClick="btnSiguiente_Click" />
                    <asp:Button ID="btnUltimo" Text=">>" Width="50" 
                      runat="server" OnClick="btnUltimo_Click" />
                </td>
            </tr>
            <tr>
                <td id="celdaPaginas" style="text-align:center" colspan="5" runat="server">
                </td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>

El diseño de la pagina se mostrará como en la siguiente figura:


Escribir el siguiente código C# en la página:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Northwind.Librerias.EntidadesNegocio; //beEmpleado
using Northwind.Librerias.ReglasNegocio; //brEmpleado
using System.Reflection; //PropertyInfo

public partial class Paginas_ListaEmpleados : System.Web.UI.Page
{
    private List<beEmpleado> lbeEmpleado;
    private int registrosPagina = 6;
    private int indicePaginaActual;
    private int indiceUltimaPagina;

    protected void Page_Load(object sender, EventArgs e)
    {
        txtPosicion.Attributes.Add("style", "text-align:center");
        if (!Page.IsPostBack)
        {
            brEmpleado obrEmpleado = new brEmpleado();
            lbeEmpleado = obrEmpleado.listar();
            Session["Empleados"] = lbeEmpleado;
            Session["Todo"] = lbeEmpleado;
            calcularPaginacion();
            enlazarDataList();
            cargarListaCampos();
        }
        else
        {
            indicePaginaActual = (int)ViewState["indicePaginaActual"];
            indiceUltimaPagina = (int)ViewState["indiceUltimaPagina"];
        }
        crearEnlacesPaginas();
    }

    private void calcularPaginacion()
    {
        indiceUltimaPagina = (lbeEmpleado.Count / registrosPagina);
        if (lbeEmpleado.Count % registrosPagina == 0)
            indiceUltimaPagina--;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        ViewState["indiceUltimaPagina"] = indiceUltimaPagina;
    }

    private void cargarListaCampos()
    {
        ddlCriterio.Items.Add(new ListItem("Todo", ""));
        PropertyInfo[] propiedades = lbeEmpleado[0].
            GetType().GetProperties();
        foreach (PropertyInfo propiedad in propiedades)
        {
            ddlCampo.Items.Add(new ListItem
                (propiedad.Name, propiedad.Name));
            ddlCriterio.Items.Add(new ListItem
                (propiedad.Name, propiedad.Name));
        }
    }

    private void crearEnlacesPaginas()
    {
        celdaPaginas.Controls.Clear();
        LinkButton lbn;
        for (int i = 0; i <= indiceUltimaPagina; i++)
        {
            lbn = new LinkButton();
            lbn.Text = (i + 1).ToString();
            lbn.Click += new EventHandler(paginar);
            celdaPaginas.Controls.Add(lbn);
            celdaPaginas.Controls.Add(new LiteralControl("  "));
        }
    }

    private void paginar(object sender, EventArgs e)
    {
        LinkButton lbn = (LinkButton)sender;
        indicePaginaActual = int.Parse(lbn.Text) - 1;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        enlazarDataList();
    }

    private void enlazarDataList()
    {
        indicePaginaActual = (int)ViewState["indicePaginaActual"];
        indiceUltimaPagina = (int)ViewState["indiceUltimaPagina"];

        lbeEmpleado = (List<beEmpleado>)Session["Empleados"];
        List<beEmpleado> lbeFiltro = new List<beEmpleado>();
        int inicio = indicePaginaActual * registrosPagina;
        int fin = (indicePaginaActual * registrosPagina) + registrosPagina;
        for (int i = inicio; i < fin; i++)
        {
            if (i < lbeEmpleado.Count) lbeFiltro.Add(lbeEmpleado[i]);
            else break;
        }
        dlsEmpleado.DataSource = lbeFiltro;
        dlsEmpleado.DataBind();
        lblRegistros.Text = lbeEmpleado.Count.ToString();
        txtPosicion.Text = String.Format("{0} de {1}", indicePaginaActual + 1,
            indiceUltimaPagina + 1);
    }

    protected void ordenarCampo(object sender, EventArgs e)
    {
        string campo = ddlCampo.SelectedValue;
        int orden = int.Parse(ddlOrden.SelectedValue);
        lbeEmpleado = (List<beEmpleado>)Session["Empleados"];
        if (orden.Equals(0)) lbeEmpleado = lbeEmpleado.OrderBy
            (x => x.GetType().GetProperty(campo).GetValue(x, null)).ToList<beEmpleado>();
        else lbeEmpleado = lbeEmpleado.OrderByDescending
            (x => x.GetType().GetProperty(campo).GetValue(x, null)).ToList<beEmpleado>();
        Session["Empleados"] = lbeEmpleado;
        enlazarDataList();
    }

    protected void filtrarCriterio(object sender, EventArgs e)
    {
        string campo = ddlCriterio.SelectedValue;
        lbeEmpleado = (List<beEmpleado>)Session["Todo"];
        if (!campo.Equals(""))
        {
            string tipo = lbeEmpleado[0].GetType().GetProperty(campo).
                PropertyType.ToString().ToLower();
            if (tipo.Contains("datetime"))
            {
                string[] fechaNac = txtDato.Text.Split('-');
                txtDato.Text = fechaNac[2] + "/" + fechaNac[1] + "/" + fechaNac[0];
            }
            lbeEmpleado = lbeEmpleado.FindAll(x => x.GetType().GetProperty(campo).
               GetValue(x, null).ToString().ToLower().Contains(txtDato.Text.ToLower()));
        }
        celdaBotones.Visible = (lbeEmpleado.Count > 0);
        Session["Empleados"] = lbeEmpleado;
        indicePaginaActual = 0;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        calcularPaginacion();
        enlazarDataList();
        crearEnlacesPaginas();
    }

    protected void btnPrimero_Click(object sender, EventArgs e)
    {
        indicePaginaActual = 0;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        enlazarDataList();
    }

    protected void btnAnterior_Click(object sender, EventArgs e)
    {
        indicePaginaActual = (int)ViewState["indicePaginaActual"];
        if (indicePaginaActual > 0) indicePaginaActual--;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        enlazarDataList();
    }

    protected void btnSiguiente_Click(object sender, EventArgs e)
    {
        indicePaginaActual = (int)ViewState["indicePaginaActual"];
        indiceUltimaPagina = (int)ViewState["indiceUltimaPagina"];
        if (indicePaginaActual < indiceUltimaPagina) indicePaginaActual++;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        enlazarDataList();
    }

    protected void btnUltimo_Click(object sender, EventArgs e)
    {
        indiceUltimaPagina = (int)ViewState["indiceUltimaPagina"];
        indicePaginaActual = indiceUltimaPagina;
        ViewState["indicePaginaActual"] = indicePaginaActual;
        enlazarDataList();
    }

    protected void cambiarControlBusqueda(object sender, EventArgs e)
    {
        string campo = ddlCriterio.SelectedValue;
        txtDato.Text = "";
        if (campo.Equals("")) txtDato.TextMode = TextBoxMode.SingleLine;
        else
        {
            lbeEmpleado = (List<beEmpleado>)Session["Empleados"];
            string tipo = lbeEmpleado[0].GetType().GetProperty(campo).
                PropertyType.ToString().ToLower();
            if (tipo.Contains("int")) txtDato.TextMode = TextBoxMode.Number;
            else
            {
                if (tipo.Contains("datetime")) txtDato.TextMode = TextBoxMode.Date;
                else txtDato.TextMode = TextBoxMode.SingleLine;
            }
        }
        enlazarDataList();
    }
}

Nota: Por defecto los registrosPorPagina está configurado a 6 y usamos Reflection para cargar dinamicamente los combos con los nombres de las propiedades del objeto empleado.

Modificar el Archivo Web.Config para especificar la cadena de conexión a Northwind

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="conNW" providerName="SQLServer" connectionString="uid=UsuarioNW;pwd=123456;
      data source=DSOFT\Sqlexpress; database=Northwind"/>
  </connectionStrings>
    <system.web>
      <compilation debug="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" />
    </system.web>
</configuration>

Probar la Pagina Web

Guardar el Sitio Web, clic derecho a la Pagina "ListaEmpleados.aspx" y seleccionar "Ver en el explorador".


Probar ir a cualquier pagina usando los Links con los números de paginas o con los botones, por ejemplo si estamos en la ultima ya no podemos avanzar a la siguiente o si estamos en la primera ya no podemos retroceder.

Seleccionar un criterio del combo "Ordenar Por", luego seleccionar el "Tipo de Orden" (ascendente o descendente) y clic al botón "Ordenar", ver como los registros se ordenan por el campo seleccionado.

Seleccionar un criterio del combo "Filtrar Por", luego ingresar un dato en "Dato Filtrar" y clic al botón "Filtrar", ver como solo aparecen los registros que cumplen con el criterio, se muestra la cantidad de registros encontrados y como varia los números de paginas.

Comentario Final

En esta demostración hemos visto como podemos paginar, ordenar y filtrar usando el control DataList y sin usar ViewState para dicho control para minimizar el HTML enviado al navegador. Mas bien hemos usado el ViewState (y no Session) para almacenar y recuperar el "indicePaginaActual" y el "indiceUltimaPagina" ya que al hacer PostBack se pierden los valores de las variables.

Descarga:
Demo14_Paginar_Ordenar_Filtrar_DataList



jueves, 17 de julio de 2014

El Demo del Día: Plantilla de Datos (Data Template) en el Control Web Repeater

Plantilla de Datos (Data Template) en el Control Web Repeater

Este es el primer Demo que estoy publicando sobre ASP .NET y trataremos de como crear Plantillas de Datos (Data Template) usando el Control Web Repeater.

Requerimientos

Se desea crear una Aplicación Web que permita listar los datos de los empleados que cumpla con lo siguiente:
- Presente en columnas la información del código, apellido, nombre y fecha de nacimiento.
- Muestre una columna con la foto del empleado la cual se encuentra en un carpeta "Empleados" donde el nombre del archivo esta compuesto por el código del empleado y la extensión jpg. Para los archivos que no se encuentren se usará el archivo No.jpg.
- La cabecera de la grilla debe estar combinada de tal forma que muestre un titulo que diga Nombre Completo que agrupe al Apellido y al nombre del empleado.
- Las filas de datos deben tener un estilo con fondo blanco y color de letra azul, pero al pasar el mouse el estilo de la fila debe tener fondo amarillo y color de letra rojo.

Nota: El principal requerimiento es que la pagina sea rápida y que arroje la menor cantidad de HTML en el cliente.

Solución

Usaremos el control Repeater y le quitaremos el ViewState (EnableViewState=false) y usaremos estilos para las filas de datos con lo cual logramos disminuir el HTML arrojado al cliente (Browser).
Ademas usando Plantilla de Datos podemos dar la apariencia que deseemos a la consulta, en este caso para combinar celdas en la cabecera.

Nota: La mayoría de programadores de ASP .NET solo consideran como alternativa usar el GridView y programar en el evento RowDataBound la combinación de las celdas y otras funcionalidades.

Crear el Procedimiento Almacenado en la Base de Datos de SQL Server

Usaremos la tabla Empleados (Employees) de Northwind:

Create Procedure [dbo].[uspEmployeesListar]
As
Select EmployeeID,LastName,FirstName,
IsNull(BirthDate,'1/1/1900') As BirthDate
From Employees Order By 1

Crear una Librería de Clases con las Entidades del Negocio

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.EntidadesNegocio" y modificar el código de la clase como sigue:

using System;
namespace Northwind.Librerias.EntidadesNegocio
{
    public class beEmpleado
    {
        public int IdEmpleado { get; set; }
        public string Apellido { get; set; }
        public string Nombre { get; set; }
        public string NombreCompleto
        {
            get
            {
                return (String.Format("{0} {1}",Nombre,Apellido));
            }
        }
        public DateTime FechaNacimiento { get; set; }
    }
}

Crear una Librería de Acceso a Datos

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.AccesoDatos" y modificar el código de la clase como sigue:

using System;
using System.Data; //CommandType
using System.Data.SqlClient; //SqlConnection, SqlCommand, SqlDataReader
using System.Collections.Generic; //List
using Northwind.Librerias.EntidadesNegocio; //beEmpleado
namespace Northwind.Librerias.AccesoDatos
{
    public class daEmpleado
    {
        public List<beEmpleado> listar(SqlConnection con)
        {
            List<beEmpleado> lbeEmpleado = null;
            SqlCommand cmd = new SqlCommand("uspEmployeesListar", con);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlDataReader drd = cmd.ExecuteReader(CommandBehavior.SingleResult);
            if (drd != null)
            {
                lbeEmpleado = new List<beEmpleado>();
                int posIdEmpleado = drd.GetOrdinal("EmployeeID");
                int posApellido = drd.GetOrdinal("LastName");
                int posNombre = drd.GetOrdinal("FirstName");
                int posFechaNacimiento = drd.GetOrdinal("BirthDate");
                beEmpleado obeEmpleado;
                while (drd.Read())
                {
                    obeEmpleado = new beEmpleado();
                    obeEmpleado.IdEmpleado = drd.GetInt32(posIdEmpleado);
                    obeEmpleado.Apellido = drd.GetString(posApellido);
                    obeEmpleado.Nombre = drd.GetString(posNombre);
                    obeEmpleado.FechaNacimiento = drd.GetDateTime(posFechaNacimiento);
                    lbeEmpleado.Add(obeEmpleado);
                }
                drd.Close();
            }
            return (lbeEmpleado);
        }
    }
}

Nota: Hay que hacer una referencia a la Librería de Entidades del Negocio.

Crear una Librería de Reglas del Negocio

Crear un proyecto de tipo Librería de Clases en C# llamado: "Northwind.Librerias.ReglasNegocio" y modificar el código de la clase como sigue:

using System;
using System.Configuration; //ConfigurationManager
namespace Northwind.Librerias.ReglasNegocio
{
    public class brGeneral
    {
        //Propiedad
        public string Conexion { get; set; }

        //Constructor
        public brGeneral()
        {
            Conexion = ConfigurationManager.ConnectionStrings["conNW"].ConnectionString;
        }
    }
}

Nota: Hay que hacer una referencia a la Librería de Entidades del Negocio, a la Librería de Acceso a Datos y a System.Configuration.

Agregar otra clase llamada: "brEmpleado" y escribir el siguiente código:

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using Northwind.Librerias.EntidadesNegocio;
using Northwind.Librerias.AccesoDatos;

namespace Northwind.Librerias.ReglasNegocio
{
    public class brEmpleado:brGeneral //Herencia
    {
        public List<beEmpleado> listar()
        {
            List<beEmpleado> lbeEmpleado = null;
            using (SqlConnection con = new SqlConnection(Conexion))
            {
                try
                {
                    con.Open();
                    daEmpleado odaEmpleado = new daEmpleado();
                    lbeEmpleado = odaEmpleado.listar(con);
                }
                catch (SqlException ex)
                {
                    //Capturar el error y grabar un Log
                }
            } //con.Close(); con.Dispose(); con = null;
            return (lbeEmpleado);
        }
    }
}

Nota: La clase "brEmpleado" hereda de la clase "brGeneral" la cadena de conexión para no pasarla como parámetro en cada método de la clase o en el constructor de cada clase se hace una sola vez.

Crear una Librería de Código de Usuario para Web

Crear un proyecto de tipo Librería de Clases en C# llamado: "General.Librerias.CodigoUsuarioWeb" y modificar el código de la clase como sigue:

using System;
using System.Collections.Generic;
using System.IO; //File
using System.Web; //HttpContext

namespace General.Librerias.CodigoUsuarioWeb
{
    public class Imagen
    {
        public static string obtenerUrl(int id, string carpeta)
        {
            string archivo = HttpContext.Current.Server.MapPath
            (String.Format("../Imagenes/{0}/{1}.jpg", carpeta, id));
            string url = String.Format("../Imagenes/{0}/{1}.jpg", carpeta, id);
            if (!File.Exists(archivo)) url = String.Format("../Imagenes/{0}/No.jpg", carpeta);
            return (url);
        }
    }
}

Nota: Como esta librería va a ser usada por paginas web hay que hacer referencia a: "System.Web"

Crear la Aplicación Web en ASP .NET Web Form

Crear un "Nuevo Sitio web vacío de ASP .NET" en C# llamado "Demo11" y crear las siguientes carpetas:
- Estilos: Para el archivo de hoja de estilo (CSS).
- Imagenes. Dentro crear otra carpeta llamada "Empleados" y adjuntar los archivos con las fotos de los empleados: 1.jpg, 2.jpg, 3.jpg, ... y No.jpg.
- Paginas: Para contener la pagina de lista de empleados.

Crear el Archivo de Hoja de Estilo (CSS)

Seleccionar la carpeta "Estilos" y agregar un archivo de hoja de estilos con el nombre de: "ACME.css" y modificar el código como sigue:

body {
    background-color:aqua;
}
.Titulo {
    background-color:black;
    color:white;
    text-transform:uppercase;
    font-size:xx-large;
    font-weight:bold;
}
.Subtitulo {
    background-color:white;
    color:blue;
    text-transform:capitalize;
    font-size:x-large;
    font-weight:bold;
}
.MarcarFila tr {
    background-color: white;
    color: blue;
    cursor:default;
    font-weight:normal;
}
.MarcarFila tr:hover {
    background-color: yellow;
    color: red;
    cursor:pointer;
    font-weight:bold;
}

Crear la Pagina ASP .NET como un Formulario Web Form

Seleccionar la carpeta "Paginas" y agregar un Formulario Web Form llamado: "ListaEmpleados.aspx", para empezar a diseñar la pagina hay que hacer referencia a las Librerías de Negocio (que copia todas sus dependencias) y la Librería de Código de Usuario Web.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ListaEmpleados.aspx.cs" Inherits="Paginas_ListaEmpleados" %>
<%@ Import Namespace="Northwind.Librerias.EntidadesNegocio" %>
<%@ Import Namespace="General.Librerias.CodigoUsuarioWeb" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link href="../Estilos/ACME.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table style="width:100%">
            <tr>
                <td class="Titulo">Plantilla y estilos en el Control Repeater</td>
            </tr>
            <tr>
                <td class="Subtitulo">Lista de Empleados</td>
            </tr>
            <tr>
                <td>
                    <asp:Repeater ID="rpEmpleado" runat="server" EnableViewState="False">
                        <HeaderTemplate>
                            <table class="MarcarFila">
                                <tr style="text-align:center;background-color:blue;color:white">
                                    <td rowspan="2" style="width:100px">Código</td>
                                    <td colspan="2" style="width:300px">Nombre Completo</td>
                                    <td rowspan="2" style="width:100px">Fecha Nac</td>
                                    <td rowspan="2" style="width:150px">Foto</td>
                                </tr>
                                <tr style="text-align:center;background-color:blue;color:white">
                                    <td style="width:150px">Apellido</td>
                                    <td style="width:150px">Nombre</td>
                                </tr>
                        </HeaderTemplate>
                        <ItemTemplate>
                            <tr>
                                <td>
                                    <%#((beEmpleado)Container.DataItem).IdEmpleado%>
                                </td>
                                <td>
                                    <%#((beEmpleado)Container.DataItem).Apellido%>
                                </td>
                                <td>
                                    <%#((beEmpleado)Container.DataItem).Nombre%>
                                </td>
                                <td>
                                    <%#((beEmpleado)Container.DataItem).FechaNacimiento.
                                       ToShortDateString()%>
                                </td>
                                <td>
                                    <img src='<%#Imagen.obtenerUrl(((beEmpleado)Container.DataItem)
                                      .IdEmpleado,"Empleados")%>' width="120" height="80" alt="Foto"
                                       title="<%#((beEmpleado)Container.DataItem).NombreCompleto%>"/>
                                </td>
                            </tr>
                        </ItemTemplate>
                        <FooterTemplate>
                            </table>
                        </FooterTemplate>
                    </asp:Repeater>
                </td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>

Nota: El código que se encuentre entre los marcadores: "<%%>" se ejecuta en el servidor, si tiene un # indica que es enlace de datos (solo se usa dentro de un control enlazado a datos). La instrucción Container.DataItem obtiene una fila enlazada a datos, en este caso un Empleado ya que el Repeater estará enlazado a una Lista de Objetos Empleados.

El diseño de la pagina se mostrará como en la siguiente figura:


Escribir el siguiente código C# en la página:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Northwind.Librerias.EntidadesNegocio; //beEmpleado
using Northwind.Librerias.ReglasNegocio; //brEmpleado

public partial class Paginas_ListaEmpleados : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            brEmpleado obrEmpleado = new brEmpleado();
            List<beEmpleado> lbeEmpleado = obrEmpleado.listar();
            rpEmpleado.DataSource = lbeEmpleado;
            rpEmpleado.DataBind();
        }
    }
}

Modificar el Archivo Web.Config para especificar la cadena de conexión a Northwind

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="conNW" providerName="SQLServer" connectionString="uid=UsuarioNW;pwd=123456;
      data source=DSOFT\Sqlexpress; database=Northwind"/>
  </connectionStrings>
    <system.web>
      <compilation debug="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" />
    </system.web>
</configuration>

Probar la Pagina Web

Guardar el Sitio Web, clic derecho a la Pagina "ListaEmpleados.aspx" y seleccionar "Ver en el explorador".


Pasar el mouse por cada fila y notar como cambia el estilo de la fila seleccionada debido al estilo "MarcarFila" aplicado a la tabla que esta dentro del control Repeater.

Clic derecho a la página y seleccionar "Ver código fuente de la pagina", notar que el HTML generado desde el servidor es mínimo ya que se le quito el ViewState al control Repeater y se uso Hojas de Estilo para reducir el formato en cada fila.

Comentario Final

Es muy útil el uso de Plantillas de Datos para personalizar la apariencia de los controles Web en ASP .NET, además es necesario entender que debemos enviar la menor cantidad de HTML al navegador para que se cargue mas rápido la página, en este caso lo logramos configurando el ViewState y usando CSS.

En los siguientes demos, estaremos viendo mas el tema de Plantillas de Datos, Hojas de Estilos y Controles Enlazados a Datos en ASP .NET.

Descarga:
Demo11_Plantilla_Repeater