我有一个objectdatasource,我想绑定到转发器。 问题是,我无法弄清楚如何显示具有可变行数的可变数量的列。
例如:
我的数据集结构如下。 objectdatasource是List<item>
。
item {
string name;
List<itemdata> data;
}
itemdata {
DateTime year;
double amount;
}
所以基本上我想制作一张桌子
| year | year | year | year
name | amount | amount | amount | amount
name | amount | amount | amount | amount
name | amount | amount | amount | amount
name | amount | amount | amount | amount
项目数量是可变的,以及项目包含的itemdata数量。
希望有人能指出我正确的方向。
由于
答案 0 :(得分:6)
您的问题的解决方案将需要三个不同的中继器,其中一个嵌套在另一个中。从这样的标记开始。
<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>
绑定到这可能有点棘手。我们的想法是,首先绑定标题行 - 然后我们绑定数据行和列。您将需要使用OnItemDataBound事件通过代码处理数据绑定,以便您可以使用必要的数据连接嵌套的转发器。
首先,我们将标题行绑定到Years。您需要隔离数据源中存在的唯一年份集合,并将其保存在私有变量中。稍后您将需要在其他中继器的数据绑定期间访问它。这将作为标题行的数据源,为每年创建一个单元格/列。
List<DateTime> _Years = dataSource.SelectMany(x => x.data).GroupBy(y => y.Year);
rptYear.DataSource = _Years;
rptYear.DataBind();
现在,您需要将Name转发器与原始数据源绑定。像
这样的东西rptName.DataSource = dataSource;
rptName.DataBind();
这将为列表中的每个项目创建一行。
在此转发器的OnItemDataBound事件期间,您需要将嵌套转发器绑定到会计年度列表 - 我们的_Years变量中每个会计年度一个 - 以及当前行数据项中的任何适用数据。这有点棘手,但我会试着解释一下:
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();
}
祝你好运。
我不得不使用多个嵌套转发器将其关闭以用于子总计和总计行之前。我开始在睡梦中看到嵌套的中继器。
答案 1 :(得分:0)
我建议您将数据转换为新的数据结构,如下所示:
name_data {
string name;
int[] amounts;
}
然后,您可以将转发器绑定到List(name_data&gt;。
要创建此项,首先,遍历item
和data
列表,并保留一份您需要报告的所有唯一年份的列表(可能是列表)。对结果列表进行排序,以便按年顺序排列。现在,年份列表的索引对应于输出表中的列号。接下来,再次遍历item
列表,这次为每个item
对象创建一个新的name_data对象。 name_data构造函数如下所示:
public name_data(string name, int yearCount) {
this.name = name;
amounts = new int[yearCount];
}
yearCount是年份列表中的项目数。
最后,逐步查看当前data
的{{1}}列表,在年份列表中查找年份以获取索引,然后将金额值保存在相应的{{中的金额字段中1}}槽。将完成的name_data添加到列表中。
完成后,您应该能够将name_data列表绑定到转发器