una ultima seleccionar seleccionados posicionarse posicionar poner obtener foco fila datos celda c# multithreading data-binding datagridview inotifypropertychanged

seleccionados - seleccionar la ultima fila de un datagridview c#



¿Cómo se actualiza correctamente una vista de datos datagrid a partir de un hilo de fondo? (3)

Tengo un objeto personalizado que implementa INotifyPropertyChanged. Tengo una colección de estos objetos donde la colección se basa en BindingList. He creado una fuente de enlace para la colección y establezco las fuentes de datos de bindingsource y datagridview.

Todo funciona muy bien, excepto que necesito actualizar las propiedades en el objeto personalizado desde los hilos de fondo. cuando lo hago, aparece el siguiente error:

BindingSource no puede ser su propia fuente de datos. No establezca las propiedades DataSource y DataMember en valores que se refieran a BindingSource

Encontré la siguiente publicación que parece tener mi problema exacto (¿y solución?) Pero no puedo entenderlo.

http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/3566f7c7-eb47-422e-ab09-9549a18da360/

Creé e inicialicé las variables de operación por la publicación en mi objeto comercial, y luego puse las dos funciones de eventos en mi clase de colección. Esto compilado correctamente, pero se cuelga sin excepción cuando se ejecuta.

He visto muchas publicaciones que dicen usar Invoke / Begin Invoke, pero no estoy llamando a ninguna función en la interfaz de usuario, simplemente estoy actualizando los objetos de negocios, por lo que no estoy seguro de dónde ubicaría las llamadas de invocación.

Una restricción: quiero que el objeto de negocio no sepa quién lo muestra (ya que hay varios consumidores), por lo que no es una opción enviar referencias de la GUI al objeto de negocio para poder llamar a invocar con esas referencias.


Como me tomé el tiempo de formatear la muestra para mis necesidades, también podría publicarla aquí como una referencia legible. Nada cambió excepto el formateo.

using System.ComponentModel; using System.Threading; namespace Utility { public class ThreadedBindingList : BindingList { SynchronizationContext ctx = SynchronizationContext.Current; protected override void OnAddingNew(AddingNewEventArgs e) { if (ctx == null) { BaseAddingNew(e); } else { ctx.Send(delegate { BaseAddingNew(e); }, null); } } void BaseAddingNew(AddingNewEventArgs e) { base.OnAddingNew(e); } protected override void OnListChanged(ListChangedEventArgs e) { // SynchronizationContext ctx = SynchronizationContext.Current; if (ctx == null) { BaseListChanged(e); } else { ctx.Send(delegate { BaseListChanged(e); }, null); } } void BaseListChanged(ListChangedEventArgs e) { base.OnListChanged(e); } } }


Encontré esta clase en un foro que funciona. Solo use esto en lugar de BindingList

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Threading; namespace Utility { public class ThreadedBindingList<T> : BindingList<T> { SynchronizationContext ctx = SynchronizationContext.Current; protected override void OnAddingNew(AddingNewEventArgs e) { if (ctx == null) { BaseAddingNew(e); } else { ctx.Send(delegate { BaseAddingNew(e); }, null); } } void BaseAddingNew(AddingNewEventArgs e) { base.OnAddingNew(e); } protected override void OnListChanged(ListChangedEventArgs e) { // SynchronizationContext ctx = SynchronizationContext.Current; if (ctx == null) { BaseListChanged(e); } else { ctx.Send(delegate { BaseListChanged(e); }, null); } } void BaseListChanged(ListChangedEventArgs e) { base.OnListChanged(e); } } }


No es seguro, pero este pequeño cambio en las respuestas anteriores podría tener un gran impacto si el hilo de fondo modifica las propiedades de los objetos más rápido de lo que se pueden mostrar;

protected override void OnListChanged(ListChangedEventArgs e) { // SynchronizationContext ctx = SynchronizationContext.Current; if (ctx == null) { BaseListChanged(e); } else if(e.ListChangedType == ListChangedType.ItemChanged) { ctx.Post(delegate { BaseListChanged(e); }, null); } else { ctx.Send(delegate { BaseListChanged(e); }, null); } }

Dé la bienvenida a cualquier sugerencia para reducir el número de llamadas publicadas si el mismo objeto se ha modificado más de una vez, y asegurándose de que cualquier llamada de envío posterior se bloqueará hasta que se hayan procesado todas las llamadas publicadas.