c# asp.net repeater nested-repeater

c# - Repetidores anidados en ASP.NET



repeater nested-repeater (4)

Descubrí que la forma más sencilla de hacer repetidores anidados sin preocuparse por los eventos de enlace de datos es simplemente configurar el DataSource con la sintaxis <%# %> .

Por ejemplo:

<asp:Repeater runat="server" id="Departments"> <ItemTemplate> Name: <%# Eval("DeptName") %> Employees: <asp:Repeater runat="server" DataSource=''<%# Eval("Employees") %>''> <ItemTemplate><%# Eval("Name") %></ItemTemplate> <SeparatorTemplate>,</SeparatorTemplate> </asp:Repeater> </ItemTemplate> </asp:Repeater>

Esto supone que su clase de Departamentos tiene una propiedad de Empleados, por ejemplo:

public class Department { public string DeptName {get; set;} public IEnumerable<Employee> Employees {get; set;} } public class Employee { public string Name {get; set;} }

Si su objeto repetidor externo no tiene una propiedad correspondiente al objeto repetidor interno, puede seguir utilizando este truco, al agregar un método en el código subyacente que hace el cálculo. Entonces su repetidor interno podría convertirse en:

<asp:Repeater runat="server" DataSource=''<%# GetEmployees(Container.DataItem) %>''>

y luego GetEmployees podría verse más o menos así:

protected IEnumerable<Employee> GetEmployees(object item) { var dept = (Department) item; // then do whatever is necessary to get the employees from dept return employees; }

Tengo una clase que contiene datos jerárquicos. Quiero presentar estos datos en mi aplicación web ASP.net utilizando repetidores anidados. ¿Cómo hago esto? Solo he hecho un nivel de anidación, ¿cómo puedo decir cinco niveles?

Cada elemento puede tener cero o muchos elementos secundarios. Básicamente estoy mellando en cada subnivel usando algunas cosas CSS. No quiero usar el control TreeView, quiero seguir estrictamente con un repetidor.

Actualizar:
Mis datos provienen de una base de datos. Tengo una tabla de datos de elementos con algunas propiedades básicas.

Item { ID, Name, Description, ... }

Entonces tengo una tabla de muchos a muchos con:

Parent { ParentID, ChildID }

Estoy iterando a través de cada elemento y mostrando sus hijos; y los hijos de sus hijos. Supongo que esto se lograría mejor con repetidores anidados, pero podría estar equivocado.


Puedes anidar repetidores sin ningún problema. Más de 2 niveles de profundidad se pone desagradable. Así es cómo:

El html se ve más o menos así:

<asp:Repeater ID="r1" runat="server" OnItemDataBound="r1_ItemDataBound"> <ItemTemplate> <!-- top level repeater element template here --> <asp:Repeater ID="r2" runat="server" onitemdatabound="r2_ItemDataBound"> <ItemTemplate> <!-- child repeater element template here --> </ItemTemplate> </asp:Repeater> </ItemTemplate> </asp:Repeater>

El código detrás se ve así:

protected void r1_ItemDataBound(object sender, RepeaterItemEventArgs e) { Repeater r2 = (Repeater)e.Item.FindControl("r2"); r2.DataSource = yourDataSourceHere; // you''ll have to query for appropriate data r2.DataBind(); } protected void r2_ItemDataBound(object sender, RepeaterItemEventArgs e) { // do the same thing here for the 3rd nested repeater if you have a third, and so on }


Siempre es más limpio tratar con el origen de datos que jugar con ItemDataBound, pero este es aún más el caso al anidar Repetidores:

<asp:Repeater DataSource="<%#ColOfCol%>" runat="server"> <ItemTemplate> <tr> <asp:Repeater DataSource="<%#Container.DataItem%>" runat="server"> <ItemTemplate> <td><%#SomeExtractingMethodLikeEval()%></td> </ItemTemplate> </asp:Repeater> </tr> </ItemTemplate> </asp:Repeater>

El origen de datos interno también podría ser una propiedad evaluada o una llamada a un método que devuelve la enumeración deseada. Solo ten en cuenta que se llamará con un objeto. Prefiero escribir la versión específica y luego sobrecargarla:

protected IEnumerable<string> GetNames(Family fam) { foreach(Person p in fam.Members) yield return p.FirstName + " " + p.Surname; } protected IEnumerable<string> GetNames(object famObj) { return GetNames((Family)famObj); }

Algo a tener en cuenta es que si desea obtener el objeto actual en el repetidor principal, debe obtenerlo con:

((RepeaterItem)Container.Parent.Parent).DataItem


<asp:Repeater ID="R1" runat="server"> <ItemTemplate> <asp:Repeater ID="R2" runat="server"> </asp:Repeater> </ItemTemplate> </asp:Repeater> R1.ItemDataBound += (s, e) => { var r2 = e.Item.FindControl("R2") as Repeater; r2.DataSource = something; r2.DataBind(); };

Tenga en cuenta que FindControl no es recursivo, solo obtendrá los elementos FindControl .