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:
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
Gracias por el demo y por compartir sus conocimiento.
ResponderBorrarProfesor, excelente demo y muchas gracias por todo el aporte.
ResponderBorrarGracias profesor por la demo.
ResponderBorrarGracias por el aporte
ResponderBorrarExcelente Demo profesor..
ResponderBorrar