Переменные столбцы повторителя - PullRequest
6 голосов
/ 19 января 2010

У меня есть объектный источник данных, который я хочу привязать к повторителю.проблема в том, что я не могу понять, как отобразить переменное количество столбцов с переменным количеством строк.

, например:

У моего набора данных такая структура.Источником objectdatasource является List<item>.

item {
  string name;
  List<itemdata> data;
}

itemdata {
  DateTime year;
  double amount;
}

, поэтому в основном я хочу создать таблицупредмет содержит.

Надеюсь, кто-то может указать мне в правильном направлении.

Спасибо

Ответы [ 2 ]

6 голосов
/ 23 января 2010

Для решения вашей проблемы потребуются три разных повторителя, один из которых вложен в другой. Начните с разметки, как это.

  <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, чтобы вы могли подключить вложенный повторитель к необходимым данным.

Сначала мы свяжем строку заголовка с Годами. Вам необходимо выделить коллекцию уникальных лет, присутствующих в вашем источнике данных, и сохранить ее в закрытой переменной. Вам потребуется доступ к нему во время привязки данных других ретрансляторов позже. Это будет служить источником данных для строки заголовка, создавая одну ячейку / столбец для каждого года.

List<DateTime> _Years =  dataSource.SelectMany(x => x.data).GroupBy(y => y.Year);
rptYear.DataSource = _Years;
rptYear.DataBind();

Теперь вам нужно привязать повторитель имени к исходному источнику данных. Что-то вроде

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

}

Удачи.

Раньше мне приходилось делать это с несколькими вложенными повторителями для промежуточных и итоговых строк. Я начал видеть вложенные повторители во сне.

0 голосов
/ 19 января 2010

Я предлагаю вам преобразовать ваши данные в новую структуру данных, например:

name_data {  
  string name;
  int[] amounts;
}

Затем вы привязали бы свой ретранслятор к списку (name_data>.

Чтобы создать это, сначала выполните итерации по спискам item и data и сохраните список (вероятно, Список) всех уникальных лет, по которым вам нужно отчитаться. Сортируйте полученный список так, чтобы годы были в порядке. Теперь индексы списка годов соответствуют номерам столбцов в вашей выходной таблице. Затем снова выполните итерацию по списку item, на этот раз создав новый объект name_data для каждого объекта item. Конструктор name_data будет выглядеть так:

public name_data(string name, int yearCount) {
  this.name = name;
  amounts = new int[yearCount];
}

YearCount - количество элементов в списке года.

Наконец, пройдитесь по списку data для текущего item, найдите год в списке годов, чтобы получить индекс, затем введите значение суммы в поле суммы в соответствующем слоте amounts. Добавьте ваши заполненные name_data в список.

Как только вы закончите, вы сможете связать свой список name_data со своим ретранслятором

...