WinForm'da DataGridView'e <T> Listesini Bağlama


93

Sınıfım var

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

ve a List<Person>bazı öğeler eklediğim. Liste benimle sınırlıdır 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;

Sorun yok. myGridiki satır görüntülüyor, ancak personslisteme yeni öğeler eklediğimde myGridyeni güncellenmiş liste göstermiyor. Yalnızca daha önce eklediğim iki satırı gösterir.

Öyleyse sorun nedir?

Her seferinde yeniden bağlama iyi çalışıyor. Ancak a'yı DataTableızgaraya bağladığımda, her zaman bazı değişiklikler DataTableyaptığımda Yeniden Bağlanmaya gerek kalmaz myGrid.

Her seferinde yeniden bağlamadan nasıl çözülür?

Yanıtlar:


192

Liste uygulanmaz, IBindingListbu nedenle ızgara yeni öğeleriniz hakkında bilgi sahibi olmaz.

BindingList<T>Bunun yerine DataGridView'ınızı bir .

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

Ama daha da ileri gidip ızgaranızı bir 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 ve diğer arayüzleri de kullanabileceğinizi söylüyor: msdn.microsoft.com/en-us/library/…
Pacane

4
@Pacane: Elbette yapabilirsiniz, ancak DataGridView'ün veri kaynağınızda herhangi bir değişiklik olup olmadığını bilmesi gerekir. Oneway, temeldeki liste değişirse bir olay oluşturacak bir BindingList kullanmaktır. Başka bir yol, BindingSourcebir Satır eklediğiniz / sildiğiniz her seferinde ResetBinding () ' i kullanmak ve çağırmaktır, ancak bu daha fazla iş demektir. Şebekeye mülk değişiklikleri hakkında bilgi vermek istiyorsanız en kolay yol uygulamaktırINotifyPropertyChanged
Jürgen Steinblock

5
Neden listeyi datagridview datasource özelliğine doğrudan bağlayabildiğimiz için BindingList ve BindingSource kullandınız. Burada kullanılan BindingList ve BindingSource u'nun önemini tartışın. teşekkürler
Mou

6
@Mou İsterseniz bir DataGrid'i a'ya bağlayabilirsiniz List<T>. Ancak Listeye programatik olarak öğe eklerseniz, DataGridView bunu bilmeyecektir çünkü List yeterli değildir IBindingList. BindingSource ile ilgili olarak: Winforms'u çok kullanıyorum ve BindingSource - FULLSTOP dışında hiçbir şeye bağlanmıyorum. Daha fazla ayrıntı eklemek, bir yorum için çok fazla, ancak BindingSourceherhangi bir dezavantaj olmadan sunacak çok şey var. Şimdiye kadar gidip şöyle derdimAnyone who does not use a BindingSource for binding has not fully understood windows forms databindings
Jürgen Steinblock

4
@CraigBrett Veri BindingSourcekaynağınız ve GUI'niz arasında bir köprü olarak düşünün . Veri bağlamayla ilgili birçok sorunu çözer. Verilerinizi yeniden yüklemek mi istiyorsunuz? bindingSource.DataSourceHer kontrolü yeniden kurmak yerine yeni koleksiyonunuza ayarlayın . Veri Kaynağınız boş olabilir mi? Küme bindingSource.DataSource = typeof(YourClass)Düzenlenebilir bir ızgaraya sahip olmak istiyorsunuz, ancak veri kaynağınızın parametresiz bir kurucusu yok mu? Sadece bindingSource.AddingNewolayı uygulayın ve nesneyi kendiniz oluşturun. Kullanırken hiçbir zaman bir dezavantaj yaşamadım BindingSourceama birçok fayda.
Jürgen Steinblock

4

Listeye her yeni eleman eklediğinizde, Izgaranızı yeniden bağlamanız gerekir. Gibi bir şey:

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;

Datagrid altında dataSource özelliğini göremiyorum.Nasıl kullanacağımı bana söyleyebilir misiniz?
RSB

2

Evet, INotifyPropertyChanged Arayüzünü uygulayarak yeniden bağlama olmadan yapmak mümkündür.

Oldukça Basit bir örnek burada mevcuttur,

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


1
Bu yeterli değildir, eğer INotifyPropertyChangedDataGridView uygularsanız , arka planda gerçekleşen tüm özellik değişikliklerini gösterecektir, ancak kaynağınızdan bir satır ekleyip silip eklemediğinizi bilemeyecektir. Bu amaçla, bir IBindingListarayüz ve sizin rahatınız BindingList<T>için, onu zaten uygulayan, ancak sıralama / filtrelemeyi desteklemeyen bir uygulama var.
Jürgen Steinblock

1
Evet, sana katılıyorum. bu yüzden ObservableCollection <T> bunun için kullanılabileceğini düşünüyorum. Ne düşünüyorsun?
Dev

0

personsEklenecek yeni öğe ekledikten sonra :

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

Datagrid altında dataSource özelliğini göremiyorum.Nasıl kullanacağımı bana söyleyebilir misiniz?
RSB

1
Bu öneri sorunlara neden olabilir. Örneğin, kılavuzdaki bir öğeye tıklamanın , veri kaynağı bu noktada boş olduğundan IndexOutOfRangeException alabileceğini bulabilirsiniz . Başlangıçta bir BindingList'e bağlanmak ve nesnenize INotifyPropertyChanged uygulamak daha akıllıca olacaktır
steve

nullHemen bir personssonraki satıra atarsanız, onu atamanın anlamı nedir ?
Rufus L

0

Bu tam olarak sahip olduğum sorun değil, ancak herhangi bir türden bir BindingList'i aynı türdeki Listeye dönüştürmek isteyen varsa, o zaman şu şekilde yapılır:

var list = bindingList.ToDynamicList();

Ayrıca, dinamik türlerin BindingLists'i DataGridView.DataSource'a atıyorsanız, bunu önce IBindingList olarak bildirdiğinizden emin olun, böylece yukarıdaki çalışır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.