ASP.NET中嵌套的中继器

我有一个包含分层数据的类。 我想使用嵌套中继器在我的ASP.net webapp中显示这些数据。 我该怎么做呢? 我只做过一层嵌套,我怎么说五层?

每个项目可以有零个或多个子项目。 我基本上只是使用一些css的东西缩进每个subleveling。 我不想使用树视图控件,我想严格坚持使用中继器。

更新:
我的数据来自数据库。 我有一个数据库的一些基本属性。

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

然后,我有一个多到许多表:

 Parent { ParentID, ChildID } 

我遍历每个项目并显示其子项; 和孩子的孩子。 我认为这是最好的嵌套中继器,但我可能是错的。

与处理数据源相比,处理数据源总是比较干净,但在嵌套中继器时更是如此:

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

内部数据源也可以是已评估的属性,也可以是对返回所需枚举的方法的调用。 只要知道它将被一个对象调用。 我更喜欢写具体的版本,然后重载:

 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); } 

有一件事要注意的是,如果你想获得在父中继器当前对象比你必须得到它:

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

我发现最简单的方法来做嵌套中继器而不用担心数据绑定事件,只是使用<%# %>语法设置数据源。

例如:

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

这假定您的Departments类具有一个Employees属性 – 例如:

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

如果您的外部中继器对象没有与内部中继器对象相对应的属性,则仍然可以使用此技巧,方法是在您的代码中添加一个用于执行计算的方法。 所以你的内在中继者可能会变成:

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

然后GetEmployees可能如下所示:

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

你可以嵌套中继器没有问题。 然而,更深层次的2级会变得讨厌。 就是这样:

这个html看起来像这样:

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

代码隐藏看起来像这样:

  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 } 
 <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(); }; 

请注意, FindControl不是recursion的,它只会得到孩子。