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]
|

