Привязка данных в DataGridView

156
18 апреля 2022, 08:40

Возникла такая проблема. У меня есть моя структура:

public struct GRIDVIEW
    {
        public List<string> kod;
        public List<string> time;
        public List<string> pers;
    }

Есть dataGridView с тремя колонками, которые я создал в конструкторе на элементе dataGridView, условно: А, В, С. Каким образом я могу привязать свою структуру как источник данных для датавьювера?

Просто dataGridView.DataSource = grid; не работает. После привязывания пустота. Даже ошибок не выдает.

Answer 1

Покажу вам настоящую привязку данных. Суть настоящей привязки в том, что вы вообще забываете о существовании DataGridView и работаете с данными.

Простой пример использования INotifyPropertyChanged и привязки данных DataBindings в Windows Forms. Обратите внимание, я нигде не использую DataSource и не обращаюсь к ячейкам, но оно работает.

public partial class Form1 : Form, INotifyPropertyChanged
{
    private BindingList<Person> _persons; // в коде не обращайтесь к полю _persons, вместо этого обращайтесь к свойству Persons
    public BindingList<Person> Persons
    {
        get => _persons;
        set
        {
            _persons = value;
            OnPropertyChanged();
        }
    }
    public Form1()
    {
        InitializeComponent();
        // вот она, привязка данных
        // DataSource - название свойства контрола, которое надо привязать
        // this - класс, в котором находится свойство с данными
        // nameof(Persons) - то же самое что строка "Persons", срока с названием самого свойства с данными
        dataGridView1.DataBindings.Add("DataSource", this, nameof(Persons));
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        Persons = new BindingList<Person>();
        Persons.Add(new Person { Name = "Иван", SurName = "Петров" });
        Persons.Add(new Person { Name = "Алексей", SurName = "Сидоров" });
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Класс с данными выглядит пострашнее, чем вы показали в вопросе, но по сути одна и та же методика повторяется везде.

public class Person : INotifyPropertyChanged
{
    private string _name;
    private string _surName;
    // если включена автогенерация колонок, заголовки колонок берутся отсюда
    [DisplayName("Имя")]
    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }
    [DisplayName("Фамилия")]
    public string SurName
    {
        get => _surName;
        set
        {
            _surName = value;
            OnPropertyChanged();
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Теперь можно с данными вытворять любые фокусы в совершенно любом месте кода и в любое время, например

Persons = new BindingList<Person>();
Persons.Add(new Person { Name = "Иван", SurName = "Петров" });
Persons[0].Name = "Вася";

А отображаемые данные будут меняться в табличке автоматически. И такую штуку можно провернуть с многими свойствами, например с Label.Text или Button.Top. Вы меняете данные, а контрол сам следит за их обновлением и обновляется, совершенно добровольно.

Кстати, соберетесь освоить WPF, UWP или Xamarin: там привязка данных - единственный способ выжить и писать вменяемые приложения, и работает точно так же как я выше показал. Так что не проходите мимо, это полезно и обязательно пригодится.

Еще один бонус привязки данных в том, что вы можете к одному свойству с данными привязать сколько угодно свойств контролов. Быть может встречали ситуацию, когда надо одно и то же записать в несколько контролов. Так вот, с привязкой данных, вы просто вяжете нужные контролы к одному свойству, а затем в коде при изменении данных в этом свойстве все привязанные контролы одновременно отреагируют на это изменение. Меньше кода - больше пользы.

Answer 2

Лучше через класс.

Вам нужно свойство DataPropertyName. Пусть есть класс, описывающий ваши данные:

public class MyClass
{
    public MyClass(string a, string b, string c)
    {
        A = a;
        B = b;
        C = c;
    }
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

В DataGridView добавим колонки:

        dataGridView.Columns.Add(new DataGridViewTextBoxColumn
                                     {
                                         DataPropertyName = "A",
                                         HeaderText = "Заголовок 1"
                                     });
        dataGridView.Columns.Add(new DataGridViewTextBoxColumn
                                     {
                                         DataPropertyName = "B",
                                         HeaderText = "Заголовок 2"
                                     });
        dataGridView.Columns.Add(new DataGridViewTextBoxColumn
                                     {
                                         DataPropertyName = "C",
                                         HeaderText = "Заголовок 3"
                                     });

Создадим коллекцию и укажем ее как источник данных:

        var data = new List<MyClass>
                       {
                           new MyClass("1", "2", "3"),
                           new MyClass("4", "5", "6"),
                           new MyClass("7", "8", "9")
                       };
        dataGridView.DataSource = data;

https://ru.stackoverflow.com/questions/311912/datagridview-привязка-данных

READ ALSO
Как окончательно сохранить ассет Scriptable object в Unity3d?

Как окончательно сохранить ассет Scriptable object в Unity3d?

В моей игре есть ассет со статистикойВ течение одной сессии всё работает прекрасно, данные спокойно перетекают по сценам

129
BackgroundService не может корректно завершиться

BackgroundService не может корректно завершиться

Не могу понять, почему мой BackgroundService (NET Core 3

164
C# переписать строку в файле

C# переписать строку в файле

Пользователь создаёт запись в файлеДалее, если нужно, он может переписать нужную запись

141
Вопрос по синтаксису вызова делегата в c# [дубликат]

Вопрос по синтаксису вызова делегата в c# [дубликат]

В общем, имеются в программе события, одно из них-CollectionCountChanged, которое генерируется функцией OnCollectionCountChanged:

123