Giải pháp cho vấn đề của bạn sẽ yêu cầu ba lặp khác nhau, một trong số đó được lồng vào bên trong khác. Bắt đầu với đánh dấu như thế này.
<table>
<tr class="headerRow">
<td> </td>
<asp:Repeater ID="rptYearHeader" runat="server" OnItemDataBound="rptYearHeader_ItemDataBound">
<ItemTemplate>
<td class="header"><asp:Literal ID="litYear" runat="server"></asp:Literal></td>
</ItemTemplate>
</asp:Repeater>
</tr>
<asp:Repeater ID="rptName" runat="server" ItemDataBound="rptName_ItemDataBound">
<ItemTemplate>
<tr>
<td><asp:Literal ID="litName" runat="server"></asp:Literal></td>
<asp:Repeater ID="rptAmounts" runat="server" OnItemDataBound="rptAmounts_ItemDataBound">
<ItemTemplate>
<td><asp:Literal ID="litAmount" runat="server"></asp:Literal></td>
</ItemTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
Việc liên kết này có thể hơi phức tạp một chút. Ý tưởng là, trước tiên chúng tôi ràng buộc hàng tiêu đề - sau đó chúng tôi ràng buộc các hàng dữ liệu và trên các cột. Bạn sẽ muốn xử lý các ràng buộc dữ liệu thông qua mã phía sau bằng cách sử dụng sự kiện OnItemDataBound để bạn có thể kết nối bộ lặp lồng nhau với các dữ liệu cần thiết.
Trước tiên, chúng tôi ràng buộc hàng tiêu đề bằng Năm. Bạn cần cô lập một tập hợp các năm duy nhất có trong nguồn dữ liệu của bạn và giữ nó trong một biến riêng tư. Bạn sẽ cần phải truy cập nó trong quá trình kết nối dữ liệu của các bộ lặp khác sau này. Điều này sẽ đóng vai trò là nguồn dữ liệu cho hàng tiêu đề, tạo một ô/cột cho mỗi năm.
List<DateTime> _Years = dataSource.SelectMany(x => x.data).GroupBy(y => y.Year);
rptYear.DataSource = _Years;
rptYear.DataBind();
Bây giờ, bạn cần phải ràng buộc bộ lặp tên với nguồn dữ liệu gốc của bạn. Một cái gì đó như
rptName.DataSource = dataSource;
rptName.DataBind();
Điều này sẽ tạo một hàng cho mỗi mục trong danh sách của bạn. Trong sự kiện OnItemDataBound cho repeater này, bạn sẽ cần phải ràng buộc repeater lồng nhau vào danh sách các năm tài chính - mỗi một năm tài chính trong biến _Years của chúng tôi - với bất kỳ dữ liệu áp dụng nào từ mục dữ liệu của hàng hiện tại. Điều này hơi phức tạp, nhưng tôi sẽ cố gắng giải thích:
protected void rptName_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// get the data item being bound
item currentItem = e.Item.DataItem as item;
// bind the item's name to the literal
//...
//
// get a list of amounts to bind to the nested repeater
// because we cant be sure that every item has amount for all years
// we create a list that we know has all years and plug in the items
// data accordingly.
List<double> amounts = new List<double>();
for (int i = 0; i < _Years.Count; i++)
{
// check whether the current item has data for the year
dataItem di = currentItem.data.Where(d => d.Year == _Years[i]).FirstOrDefault();
if(di == null)
{
// the year did not exist, so we add an amount of 0
amounts.Add(0);
}
else
{
// the year did exist, so we add that year's amount
amounts.Add(di.amount);
}
}
// we now have a list of amounts for all possible years, with 0 filling in
// where the item did not have a value for that year
// bind this to the nested repeater
rptAmounts.DataSource = amounts;
rptAmounts.DataBind();
}
Chúc may mắn.
Tôi đã phải tắt chức năng này với nhiều bộ lặp lồng nhau cho tổng số phụ và tổng số hàng trước đó. Tôi bắt đầu thấy những người lặp lại lồng nhau trong giấc ngủ của tôi.
Tôi có thể đặt bộ lặp lồng nhau vào thẻ không? –
Mike