我有一个包含分层数据的类。我想使用嵌套转发器在我的ASP.net webapp中显示这些数据。我该怎么做呢?我只做了一个级别的嵌套,我怎么说五个级别?
每个项目可以包含零个或多个子项目。我基本上只是在使用一些CSS的东西缩进每个分段。我不想使用treeview控件,我想严格坚持使用转发器。
更新:
我的数据来自数据库。我有一个带有一些基本属性的数据表。
Item
{
ID,
Name,
Description,
...
}
然后我有一对多表:
Parent
{
ParentID,
ChildID
}
我正在遍历每个项目并显示其子项;和它的孩子的孩子。我认为这最好用嵌套的中继器完成,但我可能是错的。
答案 0 :(得分:79)
我发现在不担心数据绑定事件的情况下执行嵌套转发器的最简单方法是使用<%# %>
语法设置DataSource。
例如:
<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;
}
答案 1 :(得分:33)
处理数据源总比处理ItemDataBound要干净得多,但嵌套转发器的情况更是如此:
<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>
内部数据源也可以是一个evaluate属性,或者是一个返回所需枚举的方法的调用。请注意,它将被一个对象调用。我更喜欢编写特定版本,然后重载:
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
答案 2 :(得分:11)
您可以毫无问题地嵌套转发器。然而,超过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
}
答案 3 :(得分:2)
<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
不是递归的,它只会让孩子们接受。