Répéteurs imbriqués dans ASP.NET

J'ai une classe qui contient des données hiérarchiques. Je veux présenter ces données dans mon ASP.net webapp utilisant des répéteurs imbriqués. Comment dois-je faire? Je n'ai jamais fait qu'un seul niveau d'imbrication, Comment puis-je dire cinq niveaux?

Chaque élément peut avoir zéro ou plusieurs sous-éléments. Je suis fondamentalement juste en retrait à chaque sous-nivellement en utilisant des trucs css. Je ne veux pas utiliser le contrôle treeview, je veux strictement à répétition.

Mise à jour:
Mes données proviennent d'une base de données. J'ai un élément datatable avec quelques propriétés de base.

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

Ensuite, j'ai une table plusieurs à plusieurs avec:

Parent
{
   ParentID,
   ChildID
}

Je parcourt chaque élément et affiche ses enfants; et les enfants de ses enfants. Je suppose que cela serait mieux accompli avec des répéteurs imbriqués, mais je pourrais me tromper.

37
demandé sur Mark Hurd 2010-08-26 04:55:30

4 réponses

Il est toujours plus propre de gérer la source de données que de jouer avec ItemDataBound, mais c'est encore plus le cas lors de L'imbrication de répéteurs:

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

La source de données interne peut également être une propriété évaluée ou un appel à une méthode qui renvoie l'énumération souhaitée. Sachez simplement qu'il sera appelé avec un objet. Je préfère écrire la version spécifique, puis surcharger:

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

Une chose à savoir est que si vous voulez obtenir l'objet actuel dans le parent répéteur que vous devez l'obtenir avec:

((RepeaterItem)Container.Parent.Parent).DataItem
30
répondu Jon Hanna 2015-02-10 22:08:32

J'ai trouvé que le moyen le plus simple de faire des répéteurs imbriqués sans se soucier des événements de liaison de données est de simplement définir la source de données en utilisant la syntaxe <%# %>.

Par exemple:

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

Cela suppose que votre classe de départements a une propriété Employees-par exemple:

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

Si votre objet outer-repeater n'a pas de propriété correspondant à l'objet inner-repeater, vous pouvez toujours utiliser cette astuce, en ajoutant une méthode dans votre code-behind qui fait le calcul. Si votre le répéteur interne peut devenir:

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

Et puis GetEmployees pourrait ressembler à quelque chose comme:

protected IEnumerable<Employee> GetEmployees(object item) {
  var dept = (Department) item;
  // then do whatever is necessary to get the employees from dept
  return employees;
}
75
répondu Stuart 2010-08-26 11:10:08

Vous pouvez imbriquer des répéteurs sans problème. Plus de 2 niveaux profonds devient méchant cependant. Voici comment:

Le code html ressemble à ceci:

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

Le code ressemble à ceci:

    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
    }
11
répondu Tahbaza 2010-08-26 01:06:09
<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();
};

Sachez que FindControl n'est pas récursif, il n'obtiendra que les enfants.

2
répondu BrunoLM 2010-08-26 01:06:47