Bindungsliste <T> an DataGridView in WinForm

90

ich habe ein klasse

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

und a, List<Person>zu dem ich einige Elemente hinzufüge. Die Liste ist an meine gebunden 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;

Es gibt kein Problem. myGridZeigt zwei Zeilen an, aber wenn ich meiner personsListe neue Elemente hinzufüge , myGridwird keine neue aktualisierte Liste angezeigt . Es werden nur die beiden Zeilen angezeigt, die ich zuvor hinzugefügt habe.

Was ist also das Problem?

Jedes Mal neu binden funktioniert gut. Aber wenn ich ein DataTablean das Raster binde , wenn jedes Mal, wenn ich Änderungen daran vornehme, DataTablekeine erneute Bindung erforderlich ist myGrid.

Wie kann man es lösen, ohne jedes Mal neu zu binden?

namco
quelle

Antworten:

185

Die Liste wird nicht implementiert, IBindingListsodass das Raster nichts über Ihre neuen Elemente weiß.

Binden Sie BindingList<T>stattdessen Ihre DataGridView an a .

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

Aber ich würde noch weiter gehen und dein Gitter an ein binden 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;
Jürgen Steinblock
quelle
Es heißt, dass Sie auch IList und andere Schnittstellen verwenden können: msdn.microsoft.com/en-us/library/…
Pacane
4
@Pacane: Sicher können Sie, aber die DataGridView muss wissen, ob Ihre Datenquelle Änderungen aufweist. OneSie können eine BindingList verwenden, die ein Ereignis auslöst, wenn sich die zugrunde liegende Liste ändert. Eine andere Möglichkeit besteht darin, BindingSourcejedes Mal, wenn Sie eine Zeile hinzufügen / löschen, a und ResetBinding () aufzurufen, aber das ist viel mehr Arbeit. Wenn Sie das Grid über Eigenschaftsänderungen informieren möchten, ist die Implementierung am einfachstenINotifyPropertyChanged
Jürgen Steinblock
5
Warum haben Sie BindingList und BindingSource verwendet, weil wir die Liste direkt an die Datenquelleneigenschaft datagridview binden können? Besprechen Sie die Bedeutung von BindingList und BindingSource, die hier verwendet werden. danke
Mou
5
@Mou Sie können ein DataGrid an ein binden, List<T>wenn Sie möchten. Wenn Sie jedoch programmgesteuert Elemente zur Liste hinzufügen, weiß DataGridView nichts davon, da Ihre Liste nicht implizit ist IBindingList. In Bezug auf BindingSource: Ich verwende häufig Winforms und binde an nichts anderes als an eine BindingSource - FULLSTOP. Weitere Details hinzuzufügen ist zu viel für einen Kommentar, hat aber BindingSourceohne Nachteile so viel zu bieten. Ich würde so weit gehen und sagenAnyone who does not use a BindingSource for binding has not fully understood windows forms databindings
Jürgen Steinblock
4
@CraigBrett Betrachten Sie BindingSourceals Brücke zwischen Ihrer Datenquelle und Ihrer GUI. Es löst viele Probleme im Zusammenhang mit der Datenbindung. Sie möchten Ihre Daten neu laden? bindingSource.DataSourceStellen Sie einfach Ihre neue Sammlung ein, anstatt jedes Steuerelement neu zu binden. Ihre DataSource kann null sein? Set bindingSource.DataSource = typeof(YourClass)Sie möchten ein bearbeitbares Raster haben, aber Ihre Datenquelle hat keinen parameterlosen Konstruktor? Implementieren Sie einfach das bindingSource.AddingNewEreignis und erstellen Sie das Objekt selbst. Ich habe bei der Verwendung nie einen Nachteil erlebt, BindingSourceaber viele Vorteile.
Jürgen Steinblock
4

Jedes Mal, wenn Sie der Liste ein neues Element hinzufügen, müssen Sie Ihr Raster neu binden. Etwas wie:

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;
Dimitar Dimitrov
quelle
Ich kann die dataSource-Eigenschaft unter datagrid nicht sehen. Können Sie mir sagen, wie ich sie verwende?
RSB
2

Ja, durch die Implementierung der INotifyPropertyChanged-Schnittstelle ist ein erneutes Binden möglich.

Ein ziemlich einfaches Beispiel finden Sie hier.

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

Dev
quelle
1
INotifyPropertyChangedDies ist nicht ausreichend, wenn Sie DataGridView implementieren. Es werden alle Eigenschaftsänderungen angezeigt, die im Hintergrund auftreten. Es ist jedoch nicht bekannt, ob Sie eine Zeile zu Ihrer Quelle hinzufügen oder daraus löschen. Zu diesem Zweck gibt es eine IBindingListSchnittstelle und zu Ihrer Überzeugung eine Implementierung BindingList<T>, die diese bereits implementiert, aber das Sortieren / Filtern nicht unterstützt.
Jürgen Steinblock
1
Ja, ich würde dir zustimmen. Daher denke ich, dass ObservableCollection <T> dafür verwendet werden kann. Was denken Sie?
Dev
0

Nach dem Hinzufügen eines neuen Elements zum personsHinzufügen:

myGrid.DataSource = null;
myGrid.DataSource = persons;
Rafal
quelle
Ich kann die dataSource-Eigenschaft unter datagrid nicht sehen. Können Sie mir sagen, wie ich sie verwende?
RSB
1
Dieser Vorschlag könnte Probleme verursachen. Sie können beispielsweise feststellen, dass durch Klicken auf ein Element im Raster eine IndexOutOfRangeException ausgelöst wird, da die Datenquelle zu diesem Zeitpunkt null ist. Es wäre klüger, sich zunächst an eine BindingList zu binden und INotifyPropertyChanged auf Ihrem Objekt zu implementieren, wie andere Antworten zeigen
Steve
Was ist der Sinn der Zuweisung, nullwenn Sie es sofort in personsder nächsten Zeile zuweisen ?
Rufus L
0

Dies ist nicht genau das Problem, das ich hatte, aber wenn jemand eine Bindungsliste eines beliebigen Typs in eine Liste desselben Typs konvertieren möchte, wird dies folgendermaßen durchgeführt:

var list = bindingList.ToDynamicList();

Wenn Sie einer DataGridView.DataSource Bindungslisten dynamischer Typen zuweisen, müssen Sie diese zuerst als IBindingList deklarieren, damit die oben genannten Funktionen funktionieren.

Kopfs
quelle