0

Упрощенная схема. Есть объект данных:

   class Data
    {
        public int Digit { get; set; }
    }

В коде создается список данных и привязывается к DataGridView.

List<Data> dataList = new List<Data>()
   {
     new Data(){Digit=1},
     new Data(){Digit=2},
     new Data(){Digit=1}
   };
dataGrid.DataSource = dataList;

Работает правильно - в ячейках размещены объекты Data и свойство Digit привязано к свойству DataGridCell.Value. Редактирование данных в ячейке отражается на свойстве объекта Data. Вопрос - такая схема работает для 1 колонки, а надо создать такую же схему для 10 колонок. То есть привязать матрицу Data[10][10]. Какую структуру данных надо создать для решения задачи?

Пробовал такой вариант, но выводиться не значение а имя класса

            dataGrid.Columns.Add( new DataGridViewTextBoxColumn()
            {
                HeaderText="0",
                DataPropertyName="Digit"
            } );
        dataGrid.Columns.Add( new DataGridViewTextBoxColumn()
        {
            HeaderText = &quot;1&quot;,
            DataPropertyName = &quot;Digit&quot;
        } );
        dataGrid.Rows.Add( new object[] { new Data() { Digit = 11 }, new Data() { Digit = 21 } } );
        dataGrid.Rows.Add( new object[] { new Data() { Digit = 31 }, new Data() { Digit = 33 } } );

proa
  • 11
  • В классе Data сделайте 10 свойств. – Alexander Petrov Dec 16 '20 at 09:00
  • Это и так понятно. Вопроса бы не было. Надо именно объекты. Если бы у DataGridViewCell был свой DataBindings, то все решилось бы. Но надо именно массив развернуть на Cells – proa Dec 16 '20 at 09:05
  • DataTable вам может помочь. – aepot Dec 16 '20 at 09:53
  • Где тогда у DataColumn из DataTable свойство для указания DataPropertyName, как это делается в DataGridViewColumn? – proa Dec 16 '20 at 11:35
  • Я бы написал (или поискал готовый) контрол типа грида, к которому можно прибиндить именно матрицу объектов (не список, как у стандартного грида!). Вообще, такие есть в природе. Искать лень. Когда-то я сам писал такой для матрицы вещественных чисел. Но именно простых чисел, не объектов со свойством. Хотя это не важно – Alexander Petrov Dec 17 '20 at 11:09
  • 1
    Собственно я работаю на WPF. Это случайное задание на WinForms и теперь я реально понял какая это жесть - WinFroms! – proa Dec 17 '20 at 11:25
  • Шматрицы в WPF, кстати с использованием той самой DataTable. В Winforms можно вытворять такое же самое с поправкой на пару лишних обработчиков событий для DGV, чтобы поправить ей поведение до вменяемого. Я бы может и ответил на ваш вопрос, но я его не понял. – aepot Dec 20 '20 at 22:03
  • Если любите биндинги (привязки данных) в WPF, то в Winforms тоже такое есть. – aepot Dec 20 '20 at 22:09
  • @aepot Никто не понимает, что надо но все советуют. В коде "1 ответ" есть строка кода dataTable.Columns.Add(i.ToString(), typeof(int)); Для понимания: мне надо почти тоже, но: dataTable.Columns.Add(i.ToString(), typeof(Data)); В колонку привязывается не значение а СВОЙСТВО объекта.!!! – proa Dec 22 '20 at 13:48
  • Этим кодом вы ничего не привязываете, а просто добааляете в DT колонку нужного типа. Как использовать привязку данных я вам показал. Вам осталось создать модель данных, которая будет иметь набор свойств, нужных для отображения. А строки будет представлять коллекция таких моделей. Как использовать таблицу, я вам тоже показал на примере WPF. Я не понимаю, чего вас не устраивает. – aepot Dec 22 '20 at 16:22
  • Загрузите данные в DataTable, потом выгрузите, когда надо будет сохранить. Не создавайте себе искусственные сложности. – aepot Dec 22 '20 at 16:29
  • Я так и не понял, winforms или wpf. Метки поставь правильно. – Qwertiy Dec 24 '20 at 00:45
  • @Qwertiy Да WinForms! Упоминался WPF по причине, что там можно такое, а здесь никак. Причина: у всех WPF элементов есть DataContext (свой или наследственный от родителя) и там легко можно привязать объект - а здесь не получиться - у DataGridViewCell нет свойства для привязки ОБЪЕКТА. – proa Dec 24 '20 at 16:11

1 Answers1

1

Как вам уже предложили в комментариях, можно использовать DataTable.

Допустим, имеется список объектов вашего класса: List<Data> dataList. Заполненный следующим образом:

dataList = new List<Data>();

for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) dataList.Add(new Data { Digit = i * 10 + j });

Имеется DataTable dataTable:

dataTable = new DataTable();

for (int i = 0; i < 10; i++) dataTable.Columns.Add(i.ToString(), typeof(int));

Теперь нужно смапить список на таблицу:

for (int i = 0; i < dataList.Count; i += 10)
{
    var row = dataTable.NewRow();
    for (int j = 0; j < 10; j++)
        row[j] = dataList[i + j].Digit;
    dataTable.Rows.Add(row);
}

Всё, можно сделать привязку к гриду:

dataGridView.DataSource = dataTable;

Когда пользователь поработает с данными в гриде и вам снова нужен список с объектами Data, делаем обратный маппинг:

for (int i = 0; i < 10; i++)
    for (int j = 0; j < 10; j++)
        dataList[i * 10 + j].Digit = (int)dataTable.Rows[j][i];

Теперь в dataList обновлённые данные.

Следить за индексами - ваша обязанность. Если количество объектов в списке не кратно количеству колонок в таблице - надеюсь, сами сделаете проверки.


Чтобы два раза не вставать. Во избежание тормозов, используйте грид с двойной буферизацией

class DoubleBufferedDataGridView : DataGridView
{
    protected override bool DoubleBuffered => true;
}
  • Я реально в шоке от того насколько люди не понимают о чем спрашивают. Все что написал Alexander Petrov я давно сделал. Вопрос был о ПРИВЯЗКЕ ОБЪЕКТА И ЕГО СВОЙСТВА DIGIT К DATAGRIDVIEWCELL, чтобы в реальном времени изменения в Cell передавались в объект и его свойство Digit!!! Это происходит как надо если мы к DataSource привязываем список из Data. Но получается одна колонка, а мне надо массив КОЛОНОК призязанный к массиву Data – proa Dec 17 '20 at 10:21
  • @proa - Я в шоке от того, насколько вы не знакомы с азами проектирования. Модели бизнес-логики должны быть отделены от моделей представления. Что я вам и показал. А вы пытаетесь сущности из одного слоя применить в другом, что совершенно неверно. – Alexander Petrov Dec 17 '20 at 10:43
  • @proa - люди не понимают о чем спрашивают - хех, самокритично. Вы не понимаете, о чём спрашиваете. – Alexander Petrov Dec 17 '20 at 10:44
  • Еще раз: List привязываем к DataSource. Работает как надо: свойство Digit привязано к своей колонке и редактирование этого свойства вызывает SETTER свойства Digit на объекте Data!!!! Это поведение по умолчанию для привязки. Мне надо точно такое же поведение, но не для одной колонки, а для переменного числа (2...100). То есть объект типа MatrixRow в котором есть свойство 'List Digits'. Затем привязываем список List к DataSource и получаем массив колонок привязанных к объектам из MatrixRow.Digits. Чтобы редактирование данных вызвало setter на объекте Digit. – proa Dec 17 '20 at 11:03
  • 1
    @proa - Ещё раз: одно свойство привязывается к одной колонке. Хотите десять колонок - сделайте десять свойств у привязанного объекта. – Alexander Petrov Dec 17 '20 at 11:05
  • Ну вот и открыли наконец Америку - а то я не знал. – proa Dec 17 '20 at 11:06
  • 1
    @proa - Ну вот и хорошо, теперь знаете. – Alexander Petrov Dec 17 '20 at 11:06