Я предполагаю, что вы работаете в Windows Forms. Мне удалось хотя бы отобразить данные в указанном вами формате, поместив DataGridView в Виртуальный режим . Лучше всего выполнить все прохождение для получения полного решения, но вот что я сделал в быстром тесте (взломан из образцов в пошаговом руководстве):
Обработчик CellValueNeeded:
private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
// If this is the row for new records, no values are needed.
if (e.RowIndex == this.dataGridView1.RowCount - 1) return;
DynamicNumberFieldsClass objectInRow = (DynamicNumberFieldsClass)this._people[e.RowIndex];
// Set the cell value to paint using the DynamicNumberFieldsClass object retrieved.
switch (this.dataGridView1.Columns[e.ColumnIndex].Name)
{
case "FullName":
e.Value = objectInRow.FullName;
break;
default:
e.Value = objectInRow.Years[e.ColumnIndex - 1];
break;
}
}
где _people - это коллекция DynamicNumberFieldsClass.
Форма загрузки:
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.VirtualMode = true;
this.dataGridView1.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
// Add columns to the DataGridView.
DataGridViewTextBoxColumn fullNameColumn = new
DataGridViewTextBoxColumn();
fullNameColumn.HeaderText = "FullName";
fullNameColumn.Name = "FullName";
this.dataGridView1.Columns.Add(fullNameColumn);
for (int i = 0; i < _numYears; i++)
{
DataGridViewTextBoxColumn yearIColumn = new
DataGridViewTextBoxColumn();
yearIColumn.HeaderText = "Year" + (i+1);
yearIColumn.Name = "Year" + (i+1);
this.dataGridView1.Columns.Add(yearIColumn);
}
this.dataGridView1.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
// Set the row count, including the row for new records.
this.dataGridView1.RowCount = 3; //two objects in _people and the empty row
}
где _numYears - фиксированное значение, которое вы упомянули. Если у вас есть хотя бы один экземпляр объекта, вы можете использовать размер массива Years в этом экземпляре в качестве ограничителя цикла, чтобы он был полностью динамическим.
Вам потребуется расширить оператор switch, если какие-либо другие свойства включены в класс, и, конечно, добавить дополнительную проверку ошибок в целом. В пошаговом руководстве также показано, как поддерживать редактирование в DataGridView.
(я знаю, что вы спросили, как связать столбцы, а не принудительно устанавливать их значения, поэтому вы, вероятно, хотели иметь возможность декорировать определение класса, назначить источник данных и перейти к этому. Сначала я попытался сделать это с помощью Reflection с помощью CustomTypeDescriptor, TypeDescriptionProvider и т. Д., Как можно связать свойства второго уровня. Конечно, отдельные элементы массива не отображаются как свойства, поэтому не работает. Я не могу придумать способ поддержать автоматическое создание столбцов так, как вы хотите, но, возможно, кто-то еще найдет один.)