Enlazar List <T> a DataGridView en WinForm

91

Tengo una clase

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

y una List<Person>a la que agrego algunos elementos. La lista está vinculada a mi 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;

No hay ningún problema. myGridmuestra dos filas, pero cuando agrego nuevos elementos a mi personslista, myGridno muestra una nueva lista actualizada. Solo muestra las dos filas que agregué antes.

Entonces, ¿cuál es el problema?

Rebobinar cada vez funciona bien. Pero cuando enlazo a DataTablea la cuadrícula, cuando cada vez que hago algunos cambios, DataTableno hay necesidad de volver a enlazar myGrid.

¿Cómo solucionarlo sin volver a enlazar cada vez?

Namco
fuente

Respuestas:

187

La lista no se implementa, IBindingListpor lo que la cuadrícula no conoce sus nuevos elementos.

Enlace su DataGridView a un BindingList<T>en su lugar.

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

Pero incluso iría más lejos y uniría tu cuadrícula a un 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
fuente
Dice que puede usar IList y otras interfaces también: msdn.microsoft.com/en-us/library/…
Pacane
4
@Pacane: Claro que puede, pero DataGridView necesita saber si su fuente de datos tiene algún cambio. OneLa forma es utilizar BindingList, que generará un evento si cambia la lista subyacente. Otra forma es usar BindingSourceay llamar a ResetBinding () cada vez que agrega / elimina una Fila, pero eso es mucho más trabajo. Si desea informar a Grid sobre los cambios de propiedad, la forma más fácil es implementarlosINotifyPropertyChanged
Jürgen Steinblock
5
¿Por qué usó BindingList y BindingSource porque podemos vincular directamente la lista a la propiedad de la fuente de datos datagridview? discuta la importancia de BindingList y BindingSource que usó aquí. gracias
Mou
5
@Mou Puede vincular un DataGrid a un List<T>si lo desea. Pero si agrega elementos a la lista mediante programación, DataGridView no lo sabrá porque su lista no implementa IBindingList. Con respecto a BindingSource: uso mucho winforms, y no me enlace a nada más que a BindingSource - FULLSTOP. Agregar más detalles es demasiado para un comentario, pero BindingSourcetiene mucho que ofrecer sin desventajas. Iría tan lejos y diríaAnyone who does not use a BindingSource for binding has not fully understood windows forms databindings
Jürgen Steinblock
4
@CraigBrett Considere BindingSourcecomo un puente entre su fuente de datos y su GUI. Resuelve muchos problemas relacionados con la vinculación de datos. ¿Quieres recargar tus datos? Simplemente configure bindingSource.DataSourcesu nueva colección en lugar de volver a vincular todos los controles. ¿Tu fuente de datos puede ser nula? Establecer bindingSource.DataSource = typeof(YourClass)¿Quiere tener una cuadrícula editable pero su fuente de datos no tiene un constructor sin parámetros? Simplemente implemente el bindingSource.AddingNewevento y cree el objeto usted mismo. Nunca experimenté una desventaja mientras lo usaba, BindingSourcepero muchos beneficios.
Jürgen Steinblock
4

Cada vez que agrega un nuevo elemento a la Lista, debe volver a vincular su Grid. Algo como:

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
fuente
No puedo ver la propiedad de la fuente de datos en la cuadrícula de datos. ¿Me pueden decir cómo la uso?
RSB
2

Sí, es posible hacerlo sin volver a enlazar implementando la interfaz INotifyPropertyChanged.

Un ejemplo bastante simple está disponible aquí,

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

Dev
fuente
1
Eso no es suficiente, si implementa, INotifyPropertyChangedDataGridView mostrará todos los cambios de propiedad que ocurren en segundo plano, pero no sabrá si agrega / elimina una fila de su fuente. Para ello existe una IBindingListinterfaz y, para su conveniencia, una implementación BindingList<T>que ya la implementa, pero que no admite clasificación / filtrado.
Jürgen Steinblock
1
Sí, estaría de acuerdo contigo. entonces creo que ObservableCollection <T> se puede usar para esto. ¿Qué piensas?
Desarrollador
0

Después de agregar un nuevo elemento para personsagregar:

myGrid.DataSource = null;
myGrid.DataSource = persons;
Rafal
fuente
No puedo ver la propiedad de la fuente de datos en la cuadrícula de datos. ¿Me pueden decir cómo la uso?
RSB
1
Esta sugerencia podría causar problemas. Por ejemplo, podría encontrar que un clic en un elemento de la cuadrícula podría obtener una excepción IndexOutOfRangeException ya que la fuente de datos es nula en ese punto. Sería más prudente vincularse a una BindingList inicialmente e implementar INotifyPropertyChanged en su objeto como indican otras respuestas
steve
¿Cuál es el punto de asignarlo nullsi lo asigna inmediatamente personsen la siguiente línea?
Rufus L
0

Este no es exactamente el problema que tuve, pero si alguien está buscando convertir una BindingList de cualquier tipo en una Lista del mismo tipo, entonces así es como se hace:

var list = bindingList.ToDynamicList();

Además, si está asignando BindingLists de tipos dinámicos a un DataGridView.DataSource, asegúrese de declararlo primero como IBindingList para que funcione lo anterior.

Kopfs
fuente