Вложенные репитеры в ASP.NET
У меня есть класс, содержащий иерархические данные. Я хочу представить эти данные в моем ASP.net webapp, используя вложенные репитеры. Как мне это сделать? Я только что сделал один уровень гнездования, как мне сказать пять уровней?
Каждый элемент может иметь ноль или много подпунктов. Я в основном просто отступы на каждом подуровне, используя некоторые вещи css. Я не хочу использовать элемент управления treeview, я хочу строго придерживаться ретранслятора.
Обновление:
Мои данные поступают из базы данных. У меня есть элемент данных с некоторыми базовыми свойствами.
Item
{
ID,
Name,
Description,
...
}
Затем у меня есть много-много таблиц с:
Parent
{
ParentID,
ChildID
}
Я повторяю каждый элемент и показываю его дочерние элементы; и его детей-детей. Я предполагаю, что это лучше всего выполнить с вложенными ретрансляторами, но я могу ошибаться.
Ответы
Ответ 1
Всегда полезно иметь дело с источником данных, чем возиться с 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>
Внутренний источник данных также может быть оцененным свойством или вызовом метода, который возвращает нумерацию нумерации. Просто имейте в виду, что он будет вызван с объектом. Я предпочитаю писать конкретную версию, а затем перегружать:
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
Я обнаружил, что самый простой способ сделать вложенные повторители, не беспокоясь о событиях привязки данных, - это просто установить 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;
}
Ответ 3
Вы можете встраивать репитеры без проблем. Тем не менее, более 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
}
Ответ 4
<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
не является рекурсивным, он будет получать только дети.