Список прив'язки <T> до DataGridView в WinForm


91

У мене є клас

class Person{
      public string Name {get; set;}
      public string Surname {get; set;}
}

та a, List<Person>до якого я додаю деякі елементи. Список прив'язаний до мого DataGridView.

List<Person> persons = new List<Person>();
persons.Add(new Person(){Name="Joe", Surname="Black"});
persons.Add(new Person(){Name="Misha", Surname="Kozlov"});
myGrid.DataSource = persons;

Немає жодних проблем. myGridвідображає два рядки, але коли я додаю нові елементи до свого personsсписку, myGridне відображається новий оновлений список. Він показує лише два рядки, які я додав раніше.

То в чому проблема?

Перев’язування кожного разу працює добре. Але коли я прив’язую a DataTableдо сітки, коли кожного разу, коли я вношу деякі зміни, DataTableнемає необхідності в ReBind myGrid.

Як це вирішити, не перев’язуючи кожен раз?

Відповіді:


187

Список не реалізований, IBindingListтому сітка не знає про ваші нові елементи.

BindingList<T>Натомість прив’яжіть ваш DataGridView до .

var list = new BindingList<Person>(persons);
myGrid.DataSource = list;

Але я б навіть пішов далі і прив’язав вашу сітку до BindingSource

var list = new List<Person>()
{
    new Person { Name = "Joe", },
    new Person { Name = "Misha", },
};
var bindingList = new BindingList<Person>(list);
var source = new BindingSource(bindingList, null);
grid.DataSource = source;

Там сказано, що ви також можете використовувати IList та інші інтерфейси: msdn.microsoft.com/en-us/library/…
Pacane

4
@Pacane: Звичайно, ти можеш, але DataGridView повинен знати, чи змінилося джерело даних. Oneway ist використовувати BindingList, який буде викликати подію, якщо базовий список зміниться. Інший спосіб - використовувати BindingSourceі викликати ResetBinding () кожного разу, коли ви додаєте / видаляєте рядок, але це значно більше роботи. Якщо ви хочете повідомити Grid про зміни власності, найпростіший спосіб - це здійснитиINotifyPropertyChanged
Юрген Штейнблок

5
чому ви використовували BindingList та BindingSource, тому що ми можемо безпосередньо прив’язати список до властивості datagridview datasource. обговоримо важливість BindingList та BindingSource u, що використовуються тут. спасибі
Mou

5
@Mou Ви можете прив'язати DataGrid до a, List<T>якщо хочете. Але якщо ви програмно додаєте елементи до списку, DataGridView не знатиме про це, оскільки ваш список не реалізовано IBindingList. Щодо BindingSource: я багато використовую winform, і я не прив’язую ні до чого іншого, крім BindingSource - FULLSTOP. Додавати більше деталей - це занадто багато для коментарів, але BindingSourceможна запропонувати стільки, що не має недоліків. Я зайшов би так далеко і сказавAnyone who does not use a BindingSource for binding has not fully understood windows forms databindings
Юрген Штейнблок

4
@CraigBrett Розглядайте BindingSourceяк міст між вашим джерелом даних та вашим графічним інтерфейсом. Він вирішує багато проблем, пов'язаних з прив'язкою даних. Ви хочете перезавантажити свої дані? Просто встановіть bindingSource.DataSourceдля своєї нової колекції замість того, щоб повторно пов’язувати всі елементи керування. Ваш DataSource може бути нульовим? Встановити bindingSource.DataSource = typeof(YourClass)Ви хочете мати сітку, яку можна редагувати, але у Вашому джерелі даних немає конструктора без параметрів? Просто реалізуйте bindingSource.AddingNewподію і створіть об'єкт самостійно. Я ніколи не відчував мінусів під час використання, BindingSourceале мав багато переваг.
Юрген Штейнблок,

4

Кожного разу, коли ви додаєте новий елемент до списку, вам потрібно знову прив’язати вашу сітку. Щось на зразок:

List<Person> persons = new List<Person>();
persons.Add(new Person() { Name = "Joe", Surname = "Black" });
persons.Add(new Person() { Name = "Misha", Surname = "Kozlov" });
dataGridView1.DataSource = persons;

// added a new item
persons.Add(new Person() { Name = "John", Surname = "Doe" });
// bind to the updated source
dataGridView1.DataSource = persons;

Я не бачу властивість dataSource під datagrid. Чи можете ви сказати мені, як я ним користуюся?
RSB

2

Так, можна обійтися без перев’язування, реалізувавши інтерфейс INotifyPropertyChanged.

Досить простий приклад доступний тут,

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx


1
Цього недостатньо, якщо ви реалізуєте INotifyPropertyChangedDataGridView, буде відображати всі зміни властивостей, що відбуваються у фоновому режимі, але він не знатиме, чи додаєте / видаляєте рядок із джерела. Для цього існує IBindingListінтерфейс і, для вашої зручності, доповнення, BindingList<T>яке вже реалізує його, але не підтримує сортування / фільтрування.
Юрген Штейнблок

1
Так, я б з вами погодився. тому я думаю, що ObservableCollection <T> може бути використаний для цього. Що ти думаєш?
Dev

0

Після додавання нового елемента для personsдодавання:

myGrid.DataSource = null;
myGrid.DataSource = persons;

Я не бачу властивість dataSource під datagrid. Чи можете ви сказати мені, як я ним користуюся?
RSB

1
Ця пропозиція може спричинити проблеми. Наприклад, ви можете виявити, що клацання на елементі в сітці може отримати IndexOutOfRangeException, оскільки джерело даних на цей момент є нульовим. Було б розумніше спочатку прив’язатись до BindingList та застосувати INotifyPropertyChanged на своєму об’єкті, як вказують інші відповіді
Стів

Який сенс призначати його, nullякщо ви негайно призначите його personsна наступному рядку?
Руфус Л,

0

Це не зовсім проблема, з якою я стикався, але якщо хтось хоче перетворити BindingList будь-якого типу в Список того самого типу, тоді це робиться так:

var list = bindingList.ToDynamicList();

Крім того, якщо ви призначаєте BindingLists динамічних типів DataGridView.DataSource, то переконайтеся, що спочатку оголосили його як IBindingList, щоб вищезазначене працювало.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.