Introducción
El objetivo del artículo es demostrar como linq puede ser verdaderamente potente a la hora de convertir estructuras simple y planas como ser entidades (o tablas) en objetos jerárquicos que faciliten la asignación de datos a controles, en este caso un treeview.
El resultado del artículo cargara un árbol como se muestra en la imagen, el cual podrá tener tantos niveles como uno necesite.
Recuperar los registro de forma básicaEl primer paso para armar la estructura será contar con información plana y sin procesar de la base de datos.
public static List<CategoriaEntity> ObtenerCategorias() { string sql = @"SELECT C.IdCategoria, C.IdCategoriaPadre, C.Descripcion, C.Posicion FROM Categorias C ORDER BY C.IdCategoria, C.Posicion"; List<CategoriaEntity> categorias = new List<CategoriaEntity>(); using (SqlCeConnection conn = new SqlCeConnection(ConfigurationManager.ConnectionStrings["default"].ToString())) { conn.Open(); SqlCeCommand cmd = new SqlCeCommand(sql, conn); IDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { categorias.Add(ConvertirCategoria(reader)); } } return categorias; } private static CategoriaEntity ConvertirCategoria(IDataReader reder) { return new CategoriaEntity() { IdCategoria = Convert.ToInt32(reder["IdCategoria"]), IdCategoriaPadre = reder["IdCategoriaPadre"] == DBNull.Value ? null : (int?)Convert.ToInt32(reder["IdCategoriaPadre"]), Descripcion = Convert.ToString(reder["Descripcion"]), Posicion = Convert.ToInt16(reder["Posicion"]) }; }
La información plana hay que darle jerarquía, determinando que ítem son hijos de que otros.
public static List<CategoriaJerarquica> ObtenerCategoriarJerarquia() { List<CategoriaEntity> categoriasList = ObtenerCategorias(); List<CategoriaJerarquica> query = (from item in categoriasList where item.IdCategoriaPadre == null select new CategoriaJerarquica { IdCategoria = item.IdCategoria, Descripcion = item.Descripcion, CategoriaHija = ObtenerHijos(item.IdCategoria, categoriasList) }).ToList(); return query; } private static List<CategoriaJerarquica> ObtenerHijos(int idCategoria, List<CategoriaEntity> categoriasList) { List<CategoriaJerarquica> query = (from item in categoriasList let tieneHijos = categoriasList.Where(o => o.IdCategoriaPadre == item.IdCategoria).Any() where item.IdCategoriaPadre == idCategoria select new CategoriaJerarquica { IdCategoria = item.IdCategoria, Descripcion = item.Descripcion, CategoriaHija = tieneHijos ? ObtenerHijos(item.IdCategoria, categoriasList) : null }).ToList(); return query; }
Con el primer linq al usar
where item.IdCategoriaPadre == null
se obtienen los nodos padres, o sea aquellos que no dependen de ningún otro nodo
Asignación de la jerarquía al control TreeView
Como ultimo paso y no menos importante será crear los TreeNode que requiere el control TreeView
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { List<CategoriaJerarquica> categoriaList = CategoriasDAL.ObtenerCategoriarJerarquia(); CrearNodoHijo(categoriaList, null); } } private void CrearNodoHijo(List<CategoriaJerarquica> categorias, TreeNode parentNode) { categorias.ForEach(x => { TreeNode node = new TreeNode(x.Descripcion, Convert.ToString(x.IdCategoria)); if (x.CategoriaHija != null) { CrearNodoHijo(x.CategoriaHija, node); } if (parentNode == null) TreeView1.Nodes.Add(node); else parentNode.ChildNodes.Add(node); }); }
Como se observa hay una invocación recursiva para armar la estructura del árbol.
Código de Ejemplo
El articulo fue creado con visual Studio 2008
La db es Sql Compact Edition (.sdf), por lo tanto esta se encuentra en la carpeta App_Data
[C# SkyDrive]
|
Hola Leandro retomando este tema, cree un nuevo campo llamado men_path que guarda las url de las paginas del menu por ej Inicio.aspx ,quisiera hacerte una pregunta ¿como puedo redireccionar a una pagina cuando presiono una opción del menu? ,lo he intentado pero no me resulta mucho, agradeceré tu respuesta ...gracias
ResponderEliminarhola leandro, este tipo de ejemplo se puede usar para desplegar un select box en vez de un arbol?. vi que cuando tenes mucha profundidad de categorias el arbol resulta confuso. mas que agradecido, slds.
ResponderEliminarhola Sebastian
ResponderEliminarque seria un select box ?
ese codigo sirve para armar estructurar jerarquizas con estructura de arbol, si el control que quieres suar define este tipo de estructura puedes hacerlo sin problemas
saludos
hola leandro gracias por la respuesta. por selectbox me refiero a algo como esto: http://remysharp.com/wp-content/uploads/2007/01/ebay_categories.gif
ResponderEliminarme esta costando encontrar en internet como mostrar estructuras jerarquizadas sin usar estructura de arbol. de hecho tengo una pregunta sobre ese tema en SO hace varios dias con un premio de 100 puntos y tampoco nada aparece. http://stackoverflow.com/questions/15717573/auto-populating-select-boxes-using-jquery-ajax-in-asp-net-mvc mas que agradecido por cualquier orientacion. saludos!.
hola Sebastian
ResponderEliminarpero es o es como armar controles anidados, en donde la seleccion de uno se sua como filtro del siguiente
hacerlo con ese control o con combos seria exactamente igual
en al seleccion del primer combo deberias invocar a un action del controller que devuelva el modelo con los items del segunda lista
es mas hasta podrias usar partical view con al funcionalidad ajax de asp.net mvc
Part 3 – Cascading using Microsoft AJAX (Ajax.BeginForm helper)
hay varias formas de hacerlo pero creo que usar Ajax.BeginForm() y partial view es la mejor
saludos
Leandro me sirvió muchisimo esta función!! Te agradezco.
ResponderEliminarhola buenas leandro como accederia al evento click de cada sub menu para llamar al formulario hijo??? gracias!!!!
ResponderEliminarThanks for sharing, nice post! Post really provice useful information!
ResponderEliminarGiaonhan247 chuyên dịch vụ chuyên dịch vụ mua hàng trên Amazon ship về Việt Nam uy tín, dịch vụ ebay vn nhanh chóng và dịch vụ order hàng Mỹ uy tín.