У меня есть objectdatasource, который я хочу связать с повторителем. проблема, я не могу разработать, как отобразить переменную сумму столбцов с переменной суммой строк.
например:
Набор данных, который я имею, структурирован как это. objectdatasource является a 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, который содержит объект.
Надежда кто-то может указать на меня в правильном направлении.
Спасибо
Это нормальное поведение раскладки, неповторимые объекты должны иметь их определяющий модуль импортируемым .
Вы должны быть в состоянии изменить путь модулей (I.E. из инструментов
на wistteboard.tools
), редактировав маринованные файлы, поскольку они обычно являются простыми текстовыми файлами.
Решение для вашей проблемы потребует трех разных повторителей, один из которых вложен внутри другого. Начните с разметки, как это.
<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>
Привязка к этому может быть немного сложно. Идея, сначала мы связываем ряд заголовка - тогда мы связываем строки данных и через столбцы. Вы захотите обработать привязку данных через код сзади с использованием события onitemdatuound, чтобы вы могли подключить вложенный ретранслятор с необходимыми данными.
Сначала мы связываем ряд заголовка с годами. Вам необходимо изолировать коллекцию уникальных лет, присутствующих в вашем источнике данных и сохраняйте его в частной переменной. Вам нужно будет получить доступ к нему во время привязки данных других повторителей позже. Это будет служить источником данных для строки заголовка, создавая одну ячейку / столбец для каждого года.
List<DateTime> _Years = dataSource.SelectMany(x => x.data).GroupBy(y => y.Year);
rptYear.DataSource = _Years;
rptYear.DataBind();
Теперь вам нужно связать повторитель имени с исходным источником данных. Что-то вроде
rptName.DataSource = dataSource;
rptName.DataBind();
Это создаст одну строку для каждого элемента в вашем списке.
Во время события onitemdatuound для этого повторителя вам нужно будет связать вложенный ретранслятор к списку финансовых лет - один на каждый финансовый год в нашей переменной _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();
}
Удачи.
Я должен был потянуть это с несколькими вложенными ретрансляторами для подразделений до Sub-Total и Grand Total Rows. Я начал видеть вложенные повторители во сне.
Я предлагаю вам преобразовать ваши данные в новую структуру данных следующим образом:
name_data {
string name;
int[] amounts;
}
Затем вы бы привязали свой ретранслятор к List(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 - это количество объектов в списке года.
Наконец, пройдите по списку данных
для текущего пункта
, посмотрите на год в списке, чтобы получить индекс, затем вставьте значение суммы в поле суммы в соответствующий слот суммы
. Добавьте заполненные данные name_data в список.
Как только вы закончите, вы сможете связать ваш список name_data со своим ретранслятором
.