Quiero mi bo cadillo decía ese gran filósofo moderno que es Homer Simpson. Algo parecido he estado yo pidiendo estos días. El problema se me ha presentado en una aplicación con acceso a datos, con un montaje convencional: dataset tipado + bindingsource + controles en el formulario. Uno de los campos era una fecha y podía tener valores nulos. Hasta ahí bien. El problema es que en ediciones podía recuperar el valor nulo. En esos casos, fallaba la validación de datos y no se guardaba nada, aunque tampoco conseguía saber por qué: tuve que echar mano del evento BindingComplete del BindingSource para enterarme que se producía un error en la conversión de tipos. El tipo Date no acepta nulos.
Tras una larga búsqueda en internet, casi todo en inglés, averigüé dos cosas: que era un problema común y muy molesto y que no tenía solución fácil. También hallé unas pistas que me indicaron el camino. Un trabajo no muy limpio, pero que funciona, dividido en dos partes: el enlace al control y la datatable correspondiente.
En enlace, usando el diseñador (DataBindings, Avanzado) para asignar un formato de fecha corta, queda así:
Me.txtFecha.DataBindings.Add(New Binding(«Text», Me.bsDatos, «Fecha», True, DataSourceUpdateMode.OnValidation, Nothing, «d»))
Donde Nothing representa cómo se van a mostrar los valores nulos de la base de datos, la propiedad NullValue del Binding. Ésa sabemos que funciona bien, nos interesa gestionar el otro sentido de la actualización, hacia el origen de datos. Para ello tenemos la propiedad DataSourceNullValue. Sacamos el enlace del designer y lo gestionamos a mano, creándonos el Binding:
Dim mBinding As New Binding(«Text», Me.bsDatos, «Fecha», True, DataSourceUpdateMode.OnValidation, «», «d»)
mBinding.DataSourceNullValue = Date.MinValue
Me.txtFecha.DataBindings.Add(mBinding)
Primer punto: indicamos que el NullValue para el origen de datos no va a ser DBNull (por defecto y causa de los errores), sino un valor de fecha válido, en este caso el menor valor posible (Date.MinValue).
Segundo punto: cambiamos el Nothing del NullValue por String.Empty o «». La razón es muy sencilla: NullValue nos indica dos cosas. Por una parte, si (en este caso) la fecha en la DataTable es DBNull, lo representa por lo que le indiquemos ahí. Lo segundo, si el valor de la propiedad del control (Text, en este caso) coincide con el NullValue en un cambio de datos (altas, modificaciones), le pasa al origen de datos (la DataTable) lo que le tengamos dicho en DataSourceNullValue. Y el Nothing ahí no nos vale: si no hay nada en Text, obtenemos una cadena vacía, String.Empty o «», no un valor Nothing.
Con esto, pues, si dejamos el textbox txtFecha vacío, obtendremos en el campo Fecha de la fila correspondiente un valor fecha igual a Date.MinValue. Que no es lo que queremos: buscamos un DBNull.
Eso lo hacemos en otra parte: gestionando el evento ColumChanging del DataTable. Modo rápido: en el diseñador del dataset tipado hacemos doble click sobre la columna en cuestión y nos genera el código automáticamente. En la gestión del evento incluimos el código para que nos filtre la fecha y si es igual a Date.MinValue, cambie el valor propuesto del campo a DBNull.value:
If (e.Column.ColumnName = Me.FechaColumn.ColumnName) Then
If IsDate(e.ProposedValue) AndAlso
CDate(e.ProposedValue) = Date.MinValue Then
e.ProposedValue = DBNull.Value
End If
End If
Con esto, ya tenemos nuestro campo fecha que acepta valores nulos. No es muy elegante, quizás, pero no se me ha ocurrido ninguna otra forma.
Muy Agradecido mi hermano por esto, me he quebrado la cabeza y estaba desepcionado porque en internet no encontraba nada.