ASP.NET中的嵌套中继器

Mik*_*ike 40 c# asp.net repeater nested-repeater

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

每个项目可以有零个或多个子项目.我基本上只是在使用一些CSS的东西缩进每个分段.我不想使用treeview控件,我想严格坚持使用转发器.

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

Item
{
   ID,
   Name,
   Description,
   ...
}
Run Code Online (Sandbox Code Playgroud)

然后我有一个多对多的表:

Parent
{
   ParentID,
   ChildID
}
Run Code Online (Sandbox Code Playgroud)

我正在遍历每个项目并展示它的孩子; 和它的孩子的孩子.我认为这最好用嵌套的中继器完成,但我可能是错的.

Stu*_*art 80

我发现在不担心数据绑定事件的情况下进行嵌套转发器的最简单方法是使用<%# %>语法设置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>
Run Code Online (Sandbox Code Playgroud)

这假设你的Departments类有一个Employees属性 - 例如:

public class Department {
  public string DeptName {get; set;}
  public IEnumerable<Employee> Employees {get; set;}
}
public class Employee {
  public string Name {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

如果您的外部转发器对象没有与内部转发器对象相对应的属性,您仍然可以使用此技巧,方法是在代码隐藏中添加一个执行计算的方法.所以你的内心转发器可能会成为:

<asp:Repeater runat="server" DataSource='<%# GetEmployees(Container.DataItem) %>'>
Run Code Online (Sandbox Code Playgroud)

然后GetEmployees可能看起来像:

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

  • @John它显然是某种具有Name属性的对象的枚举. (3认同)
  • @Jon:呃.真?这对我来说很清楚,但也许不是下一千个阅读这个答案的人. (3认同)
  • 完成.我还添加了一个关于如何处理Department没有Employees属性的情况的说明. (3认同)

Jon*_*nna 34

处理数据源总是比使用ItemDataBound搞乱更简洁,但在嵌套Repeater时更是如此:

<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>
Run Code Online (Sandbox Code Playgroud)

内部数据源也可以是一个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);
}
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是,如果要获取父转发器中的当前对象,则必须使用以下方法获取它:

((RepeaterItem)Container.Parent.Parent).DataItem
Run Code Online (Sandbox Code Playgroud)

  • 这是一个偏好的问题.我不喜欢在aspx中嵌入绑定逻辑,然后仍然不得不求助于代码隐藏的任何复杂性. (3认同)

Tah*_*aza 12

您可以毫无问题地嵌套转发器.然而,超过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>
Run Code Online (Sandbox Code Playgroud)

代码隐藏看起来像这样:

    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
    }
Run Code Online (Sandbox Code Playgroud)

  • @Jon:回复你的评论如下; 我发现我的方法对于更复杂的绑定逻辑更具可扩展性和更少丑陋; 例如,除了父上下文之外,还需要用于当前安全性上下文的过滤器. (5认同)
  • 它变得令人讨厌,但你使用不必要的itemdatabound处理程序而不仅仅使用数据源使它更糟糕. (2认同)