lunes, 10 de noviembre de 2014

El Demo del Día: Selección Jerárquica en TreeView con CheckBox

Selección Jerárquica en TreeView con CheckBox

En este post veremos como trabajar en una aplicación Windows Forms con un TreeView que tenga CheckBoxes para poder seleccionar en forma jerárquica varios nodos al marcar o desmarcar el check del nodo padre.

Requerimientos

- Se desea llenar en forma dinámica un control TreeView (estructura jerárquica) desde una Lista de Objetos (estructura matricial).

- El TreeView debe contener CheckBox para cada elemento.

- Al marcar o desmarcar el Check de un nodo deberían marcarse o desmarcarse todos sus nodos hijos.

Solución

- Usaremos el Control TreeView de Windos Forms y configuraremos la propiedad "CheckBoxes" en true para habilitar los Checks en cada nodo.

- Se usará la recursividad para cargar la lista de objetos en los nodos.

- Finalmente en el evento "AfterCheck" usando también recursividad se marcara o desmarcara los nodos hijos del nodo padre.

Crear una Aplicación Windows Forms en C#

En Visual Studio crear un proyecto Windows Forms en C# con el nombre de "TreeView_CheckBox", luego cambiar el nombre del formulario a "frmListaEmpleados".

Agregar una Clase Entidad de Negocio para el Empleado

Crearemos un ejemplo que trabaje con una lista de empleados que se cargará desde una Lista de Objetos que se llena manualmente pero puede obtenerse desde una base de datos.

Para esto hay que crear una clase llamada "beEmpleado.cs", y escribir el siguiente código:

using System;
namespace TreeView_CheckBox
{
    public class beEmpleado
    {
        public int IdEmpleado { get; set; }
        public string Nombres { get; set; }
        public int IdJefe { get; set; }
    }
}

Crear el Formulario con el TreeView con CheckBoxes

En el formulario llamado "frmListaEmpleados" agregar un TreeView llamado "tvwEmpleado" y acoplarlo a toda la ventana (Dock en Fill), luego configurar la propiedad "CheckBoxes" en true, tal como se muestra en la siguiente figura:


Escribir el siguiente código en el formulario:

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

namespace TreeView_CheckBox
{
    public partial class frmListaEmpleados : Form
    {
        List<beEmpleado> lbeEmpleado;

        public frmListaEmpleados()
        {
            InitializeComponent();
        }

        private void obtenerEmpleados()
        {
            lbeEmpleado = new List<beEmpleado>();
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 1, Nombres = "Luis Dueñas", IdJefe = 0 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 2, Nombres = "Arturo Castañeda", IdJefe = 1 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 3, Nombres = "Enrique Espinal", IdJefe = 1 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 4, Nombres = "Maria Rojas", IdJefe = 2 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 5, Nombres = "Juan Perez", IdJefe = 2 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 6, Nombres = "Rosa Toro", IdJefe = 3 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 7, Nombres = "Pedro Vasquez", IdJefe = 3 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 8, Nombres = "Cesar Ramirez", IdJefe = 5 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 9, Nombres = "Ana Rodriguez", IdJefe = 6 });
        }

        private void listarEmpleados(object sender, EventArgs e)
        {
            obtenerEmpleados();
            TreeNode nodoRaiz = new TreeNode(lbeEmpleado[0].Nombres);
            nodoRaiz.Tag = lbeEmpleado[0].IdEmpleado.ToString();
            tvwEmpleado.Nodes.Add(nodoRaiz);
            llenarTreeView(nodoRaiz);
            tvwEmpleado.ExpandAll();
        }

        private void llenarTreeView(TreeNode nodoPadre)
        {
            int idJefe = int.Parse(nodoPadre.Tag.ToString());
            List<beEmpleado> lbeFiltro = lbeEmpleado.FindAll(x => x.IdJefe.Equals(idJefe));
            if (lbeFiltro != null && lbeFiltro.Count > 0)
            {
                TreeNode nodoHijo;
                foreach (beEmpleado obeEmpleado in lbeFiltro)
                {
                    nodoHijo = new TreeNode(obeEmpleado.Nombres);
                    nodoHijo.Tag = obeEmpleado.IdEmpleado.ToString();
                    nodoPadre.Nodes.Add(nodoHijo);
                    llenarTreeView(nodoHijo);
                }
            }
        }

        private void seleccionarNodoEmpleado(object sender, TreeViewEventArgs e)
        {
            TreeNode nodoJefe = e.Node;
            seleccionarEmpleadosPorJefe(nodoJefe);
        }

        private void seleccionarEmpleadosPorJefe(TreeNode nodoJefe)
        {
            foreach (TreeNode nodoEmpleado in nodoJefe.Nodes)
            {
                nodoEmpleado.Checked = nodoEmpleado.Parent.Checked;
            }
        }
    }
}

Nota: El método "listarEmpleados" esta asociado al evento "Load" del formulario y el método "llenarTreeView" esta asociado al evento "AfterCheck" del TreeView llamado "tvwEmpleado".

Se está usando la propiedad Text de cada nodo (objeto TreeNode) para mostrar el Nombre del Empleado pero se usa la propiedad Tag para guardar el Id del Empleado.

Hay que comentar que al seleccionarse un nodo hijo nuevamente se dispara el evento "AfterCheck" es por eso que no se debe llamar al método "seleccionarEmpleadosPorJefe" así mismo ya que de por si se hace la recursividad por el evento.

Probar la Aplicación Windows Forms

Grabar la aplicación y ejecutarla con F5. Se mostrará la siguiente ventana:


Marcar el check de cualquier empleado y se marcarán todos sus subordinados, tal como se muestra en la siguiente figura:


Ahora probar a desmarcar y se desmarcan todos sus dependencias gracias a la recursividad del evento "AfterCheck".

Comentario Final

En este post vimos como trabajar con un TreeView con CheckBoxes y poder marcar o desmarcar jerárquicamente usando recursividad. Espero les sirva este ejemplo y lo mismo sería para Web.

Ya saben que se aceptan pedidos. Los pedidos mas interesantes serán considerados para programarlos y subirlos al Blog.

Descarga

El Libro del Día: Illustrated WPF

El Libro del Día: 2014-11-10

Titulo: Illustrated WPF
Autor: Daniel Solis
Editorial: Apress
Nro Paginas: 531

Capítulos:
CHAPTER 1 Introduction to Windows Presentation Foundation
CHAPTER 2 Overview of WPF Programming
CHAPTER 3 WPF Architecture and Applications
CHAPTER 4 XAML
CHAPTER 5 Layout
CHAPTER 6 Content and Controls
CHAPTER 7 Dependency Properties
CHAPTER 8 Data Binding
CHAPTER 9 Routing Events and Commands
CHAPTER 10 Other Controls and Elements
CHAPTER 11 Resources
CHAPTER 12 Styles
CHAPTER 13 Control Templates
CHAPTER 14 Page Navigation Programs
CHAPTER 15 More Data Binding
CHAPTER 16 Trees, Tabs, and Other Controls
CHAPTER 17 Text and Documents
CHAPTER 18 Graphics in WPF
CHAPTER 19 Animation
CHAPTER 20 Audio and Video

Descarga:
Illustrated_WPF