Mostrando las entradas con la etiqueta Directory. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Directory. Mostrar todas las entradas

viernes, 28 de noviembre de 2014

El Demo del Día: Preview de Imágenes en un TreeView de Directorios en WebForms

Preview de Imágenes en un TreeView de Directorios en WebForms

En este breve post veremos como mostrar los directorios de una cierta carpeta de la Aplicación Web, por ejemplo de las Imágenes. Para esto usaremos el control TreeView para mostrar jerárquicamente los directorios y el control Repeater para listar los archivos y ver las imágenes del directorio seleccionado.

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

Crear un "Nuevo Sitio web vacío de ASP .NET" en C# llamado "TreeViewDirectorios_PreviewImagenes". Crear la siguiente estructura de carpetas en el proyecto:
- Estilos: Contiene el archivo de hoja de estilo ACME.css
- Imagenes: Contiene las carpetas Empleados y Productos
  - Empleados: Contiene archivos de los empleados del 01.jpg al 08..jpg
  - Productos: Contiene las siguientes carpetas
    - Bebidas: Contiene archivos jpg con bebidas.
    - Condimentos: Contiene archivos jpg con condimentos.
    - Confecciones: Contiene archivos jpg con confecciones.
- Paginas: Contiene el formulario web VisorImagenes.aspx

Crear el Archivo de Hoja de Estilo

En la carpeta "Estilos" agregar un archivo de hoja de estilo llamado "ACME.css" y escribir lo siguiente:

body {
    background-color:lightgray;
}
.Titulo {
    background-color:black;
    color:white;
    text-transform:uppercase;
    font-size:xx-large;
    font-weight:bold;
}
.Subtitulo {
    background-color:white;
    color:black;
    text-transform:capitalize;
    font-size:x-large;
    font-weight:bold;
}
.Imagen {
    width:120px;
    height:100px;
    border:solid;
    border-width:20px;
    border-color:lightgray;
}

.Imagen:hover {
    cursor:pointer;
    border:solid;
    border-width:20px;
    border-color:yellow;
}

Crear la Pagina como Formulario WebForm

En la carpeta "Paginas" agregar un formulario WebForm llamado: "VisorImagenes.aspx" y escribir lo siguiente:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="VisorImagenes.aspx.cs" Inherits="TreeViewDirectorios_PreviewImagenes.Paginas.VisorImagenes" %>
<!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>
            <tr class="Titulo">
                <td colspan="2">Preview de Imagenes en un TreeView de Directorios</td>
            </tr>
            <tr class="Subtitulo">
                <td colspan="2">Creado Por: Luis Duenas</td>
            </tr>
            <tr>
                <td style="vertical-align:top">
                    <asp:TreeView ID="tvwDirectorio" runat="server"
                        OnSelectedNodeChanged="mostrarImagenesDirectorio"/>
                </td>
                <td>
                    <asp:Repeater ID="rptImagen" EnableViewState="false" runat="server">
                        <ItemTemplate>
                            <img src="<%#obtenerUrl(Container.DataItem.ToString())%>"                              
                                title="<%#obtenerNombre(Container.DataItem.ToString())%>"
                                class="Imagen" alt="" />
                        </ItemTemplate>
                    </asp:Repeater>
                </td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>

Nota: Es importante que se desactive el ViewState del Repeater para dismunir el HTML generado en el cliente, ya que no es necesario, porque en el servidor se esta enlazando el control Repeater cada vez que se elige un directorio (optmización del HTML enviado al cliente).

El diseño de la pagina debe mostrase similar a la siguiente figura:

Escribir el siguiente código C# para la pagina:

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

namespace TreeViewDirectorios_PreviewImagenes.Paginas
{
    public partial class VisorImagenes : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                string ruta = Server.MapPath("../Imagenes");
                IEnumerable<string> listaDirectorios = Directory.EnumerateDirectories(ruta);
                TreeNode nodoRaiz = new TreeNode("Imagenes");
                tvwDirectorio.Nodes.Add(nodoRaiz);
                llenarNodos(nodoRaiz, listaDirectorios);
                tvwDirectorio.ExpandAll();
                tvwDirectorio.SelectedNodeStyle.BackColor = Color.Yellow;
                tvwDirectorio.SelectedNodeStyle.ForeColor = Color.Red;
            }
        }

        private void llenarNodos(TreeNode nodoPadre, IEnumerable<string> listaDirectorios)
        {
            foreach(string directorio in listaDirectorios)
            {
                TreeNode nodo = new TreeNode(Path.GetFileName(directorio));
                nodoPadre.ChildNodes.Add(nodo);
                IEnumerable<string> lista = 
                Directory.EnumerateDirectories(Path.Combine(Server.MapPath("../"), 
                nodo.ValuePath));
                if(lista.Count() > 0) llenarNodos(nodo, lista);
            }
        }

        protected void mostrarImagenesDirectorio(object sender, EventArgs e)
        {
            string directorio = Path.Combine(Server.MapPath("../"),
            tvwDirectorio.SelectedNode.ValuePath.Replace(@"/", @"\"));
            IEnumerable<string> archivos = Directory.EnumerateFiles(directorio, "*.jpg");
            rptImagen.DataSource = archivos;
            rptImagen.DataBind();
        }

        protected string obtenerUrl(string archivo)
        {
            return String.Format("../{0}/{1}", 
            tvwDirectorio.SelectedNode.ValuePath,Path.GetFileName(archivo));
        }

        protected string obtenerNombre(string archivo)
        {
            return Path.GetFileName(archivo);
        }
    }
}

Nota: Para leer directorios estamos usando Directory.EnumerateDirectories y para leer archivos estamos usando Directory.EnumerateFiles que es la forma mas eficiente de leer en .NET ya que solo crea un registro a la vez (consume menos memoria y es mas rápido).
Además se usa una función recursiva para llenar el TreeView con los directorios llamada "llenarNodos" que usa la propiedad ValuePath que obtiene la ruta del nodo actual.
También se definen 2 métodos protegidos: "obtenerUrl" y "obtenerNombre" que se usan en el HTML del Repeater.

Probar la Pagina Web

Guardar el Sitio Web, clic derecho a la Pagina "VisorImagenes.aspx" y seleccionar "Ver en el explorador". Se mostrará una ventana similar a la siguiente figura:


Observar como se muestra todas lar carpetas creadas dentro de la carpeta "Imagenes" en el TreeView, ahora seleccionar un directorio, por ejemplo "Empleados" y se mostrará las imágenes que esta contiene, similar a la siguiente figura:


Notar que al poner el mouse sobre una imagen se muestra como tooltip el nombre del archivo de imagen.

Ahora seleccionar otro directorio, por ejemplo "Bebidas" y disminuir el ancho del navegador (como si fuera una Tabla) y se muestra menos columnas pero el Diseño Web es Adaptativo (Responsive Web Design), tal como se ve en la siguiente figura:



Para finalizar, seleccionar otro directorio, por ejemplo "Condimentos" y disminuir aún mas el ancho del navegador (como si fuera un Teléfono Celular) y nuevamente el diseño se adapta mostrando una sola columna, tal como se ve en la siguiente figura:



Comentario Final

En este pequeño demo, hemos visto como llenar un TreeView en WebForms con los directorios de una cierta carpeta usando una función recursiva, además de como hacer el preview de su contenido usando un control Repeater y Plantillas de Datos con código incrustado en el servidor (las 2 funciones obtener). Además para mejorar la apariencia se hace usado hojas de estilo (CSS).

A los visitantes del Blog que no han sido alumnos míos y que a veces tienen pedidos que se hacen en clases en el programa PECI .NET o Web Developer, no es mi intención repetir lo que se ve en clases, sino, publicaríamos un Demo diario y el tiempo no me alcanzaría.

Saludos a todos y recuerden la frase: "Somos lo que pensamos de nosotros mismos".

Descarga


viernes, 26 de septiembre de 2014

El Demo del Día: Visor de Imágenes con Zoom en WinForms

Visor de Imágenes con Zoom en WinForms

Este post es a pedido de un alumno que quiere una aplicación en Windows Forms que muestre una secuencia de Imágenes y pueda realizar el Zoom.

Crear la Aplicación Windows Forms

Primero crearemos una aplicación en Windows Forms en C# llamada: "VisorImagenesZoom".
Cambiar de nombre al formulario por el de "frmVisor", luego diseñar la pantalla como se muestra en la siguiente figura:


Nota: También hay que incluir un Timer llamado "tmrPreview" que cada 3 segundos muestre las imágenes del directorio seleccionado.

Escribir el siguiente código en el formulario:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

namespace VisorImagenesZoom
{
    public partial class frmVisor : Form
    {
        private int c;
        private int n;
        private Point punto1;

        public frmVisor()
        {
            InitializeComponent();
        }

        private void abrirDirectorio(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog().Equals(DialogResult.OK))
            {
                txtDirectorio.Text = fbd.SelectedPath;
                IEnumerable<string> archivos = Directory.EnumerateFiles(fbd.SelectedPath, "*.jpg");
                lstArchivo.Items.Clear();
                lstArchivo.BeginUpdate();
                foreach (string archivo in archivos)
                {
                    lstArchivo.Items.Add(Path.GetFileNameWithoutExtension(archivo));
                }
                lstArchivo.EndUpdate();
                txtTotalArchivos.Text = lstArchivo.Items.Count.ToString();
                tmrPreview.Enabled = true;
                tmrPreview.Start();
            }
        }

        private void mostrarImagenes(object sender, EventArgs e)
        {
            lstArchivo.SelectedIndex = c;
            string archivo = Path.Combine(txtDirectorio.Text, lstArchivo.Items[c].ToString() + ".jpg");
            picPreview.LoadAsync(archivo);
            c++;
            if (c == lstArchivo.Items.Count) c = 0;
        }

        private void configurarZoom(object sender, MouseEventArgs e)
        {
            if (e.Button.Equals(MouseButtons.Left))
            {
                if (n == 0)
                {
                    punto1 = e.Location;
                    tmrPreview.Stop();
                    tmrPreview.Enabled = false;
                }
                else
                {
                    if (n == 1)
                    {
                        Point punto2 = e.Location;
                        string archivo = Path.Combine(txtDirectorio.Text,
                                                   lstArchivo.Items[c].ToString() + ".jpg");
                        Bitmap bmp = new Bitmap(picPreview.Image);
                        Bitmap bmpZoom = new Bitmap(bmp.Width, bmp.Height);
                        Graphics g = Graphics.FromImage(bmpZoom);
                        float ratioX = (bmp.Width/picPreview.Width);
                        float ratioY = (bmp.Height / picPreview.Height);
                        int posX = (int)(ratioX * punto1.X);
                        int posY = (int)(ratioY * punto1.Y);
                        int ancho = (int)(ratioX*(punto2.X-punto1.X));
                        int alto = (int)(ratioY * (punto2.Y - punto1.Y));
                        Rectangle srcRect = new Rectangle(posX, posY, ancho, alto);
                        Rectangle dstRect = new Rectangle(0, 0, bmpZoom.Width, bmpZoom.Height);
                        g.DrawImage(bmp, dstRect, srcRect, GraphicsUnit.Pixel);
                        picPreview.Image = bmpZoom;
                        tmrPreview.Enabled = true;
                        tmrPreview.Start();
                    }
                }
                n++;
                if (n == 2) n = 0;
            }
        }
    }
}

Nota: Para programar el Zoom se ha asociado al evento MouseClick del PictureBox llamado "picPreview" donde en el primer clic se captura la ubicación del punto y se guarda en una variable "punto1" y en el segundo clic se captura el punto2 y se crea un rectangulo con la imagen para el Zoom. Solo hay que tener en cuenta que el Rectangulo debe ser en base a la imagen (Bitmap) del PictureBox y No al tamaño del control (con propiedad SizeMode en StrechImage), por lo cual se crea las variables ratios.

Probar la Aplicación Creada

Grabar el proyecto y ejecutarlo con F5. Seleccionar un directorio donde se encuentren archivos jpg y se mostraran en la lista tal como aparece en la siguiente figura:


Cada 3 segundos cambiara la imagen y se seleccionara en la lista el archivo que se esta mostrando, dar el primer clic sobre la imagen y luego el segundo clic mostrará el preview de la imagen, tal como sigue:


Comentario Final

En este post hemos visto como mostrar una secuencia de imágenes usando un Timer y también como realizar el Zoom de una Imagen usando el método DrawImage de la clase Graphics para dibujar un rectángulo con la imagen especificada al dar dos clics, uno para marcar el punto de inicio y otro para marcar el punto final.

Descarga:
Demo19_VisorImagenesZoom