28 diciembre 2006

Controlando errores en DataGridView y cancelando líneas nuevas

Hoy vamos a por varios problemillas relacionados con el DataGridView enlazado a una colección de objetos de negocio. Los resumo muy brevemente:
  1. Ya corregí la eliminación de líneas. Originalmente sólo hacía un remove, por lo que la entidad seguía existiendo en la base de datos. Ahora hay una nueva propiedad en la colección que elimina las entidades al quitarlas de la colección en memoria, con lo que ya funciona la eliminación de líneas desde el DataGridView (dgv) sin necesidad de código específico.
  2. Cuando se mete uno en la línea nueva, nada más hacer clic, el dgv ya la trata como una línea existente y crea una nueva debajo. Sucede incluso antes de que el usuario intente escribir algo. Para empezar, este comportamiento no me gusta. Preferiría que se añadiera cuando los datos sean válidos. Pero claro, se necesita una entidad por debajo, y esa entidad debe estar en la colección... así que es posible que no se pueda cambiar el comportamiento. Aún así tenemos 2 alternativas: a) si intenta abandonarse la línea sin estar correcta, ofrecer eliminarla o quedarse en ella para corregirla; b) si se pulsa ESC, debe eliminarse la línea (esto según leo funciona en los dgv asociados a un DataSet automáticamente. ¿Por qué a nosotros no?)
  3. La gestión de errores en un dgv es diferente: las filas (o las celdas) tienen un ErrorText, y parece que si se rellena, aparece un icono de error en el selector de la fila. Vamos a ver cómo puedo facilitar su uso desde nuestras colecciones de negocio.
Tras varias horas (unas 6) he encontrado a qué se debe el problema de las líneas nuevas, y he consiguido que al pinchar en ella o moverme a ella, no se cree inmediatamente otra debajo. Era culpa del evento PropertyChanged disparado por la colección origen de datos del grid (en el caso de mis pruebas, culpa del evento disparado por Provincia de que había cambiado su colección de Poblaciones). El evento provocaba un refresco del enlace (del BindingSource), que se producía durante el AddNew, confirmándolo y fastidiándolo. Para evitarlo y solucionar de un plumazo todos los problemas del punto 2, creamos un método EBase.OnPropertyCollectionChanged que no dispara el PropertyChanged, sólo pone el objeto a sucio. En caso de que tengamos que propagar la suciedad más allá (por ejemplo, Población no sólo a Provincia, sino de ahí a País) tenemos que crear un método específico (ver NotificarCambioEnPoblaciones) para evitar disparar los eventos que refrescarían los controles dgv enlazados a colecciones de negocio.
Antes que esto había conseguido mostrar los errores, provisionalmente lo hago a nivel de línea y con código específico para cada dgv, aunque podría generalizarse. Sólo hay que rellenar la propiedad ErrorText de la Row, o bien de la Cell si queremos mostrar en cada celda su círculo rojo de error. También queda pendiente controlar esto conjuntamente con PieErrores, de forma que éste se ponga en rojo cuando haya fallos en algún dgv.