可变中继器列

时间:2010-01-19 01:04:20

标签: asp.net data-binding repeater

我有一个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数量。

希望有人能指出我正确的方向。

由于

2 个答案:

答案 0 :(得分:6)

您的问题的解决方案将需要三个不同的中继器,其中一个嵌套在另一个中。从这样的标记开始。

  <table>
       <tr class="headerRow">
          <td> &nbsp;</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;。

要创建此项,首先,遍历itemdata列表,并保留一份您需要报告的所有唯一年份的列表(可能是列表)。对结果列表进行排序,以便按年顺序排列。现在,年份列表的索引对应于输出表中的列号。接下来,再次遍历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列表绑定到转发器