Un formulario para varias tablas

Digamos que tengo una docena de tablas con la misma estructura: 3 campos (Id para la clave primaria, Nombre y Descripción) con las mismas características. Estas tablas, además, van a tener pocos registros, no llegarán a 20. Concretamente, forman parte de una base de datos de series y películas y almacenan los datos de, por ejemplo, códecs, formatos de archivo, resoluciones, el soporte (DVD, CD, disco duro) donde están almacenados, etc. La pregunta es ¿cómo gestiono el contenido de estas tablas (altas, bajas y modificaciones)? A cada cual se le ocurrirá una opción, la mía, con pocas ganas de complicarme la vida, es la siguiente:

Tengo un formulario sencillo con los siguientes elementos: un ListBox que mostrará el nombre de todos los elementos de la tabla y servirá para navegar por los registros, dos TextBox, uno para el Nombre y otro para la Descripción, con sus respectivas etiquetas, y los controles necesarios para la gestión (podrían ser botones, pero yo uso un MenuStrip): Nuevo, Modificar, Eliminar, Aceptar y Cancelar. Añadimos un BindingSource a la ecuación y, si nos olvidamos por el momento de la generación de la clave primaria, esto ya está hecho, independientemente de lo que pongamos debajo del BindingSource.

Por otro lado, tengo 12 datasets tipados, cada uno con una de las tablas en cuestión. Tienen una pequeña personalización adicional: se controla el evento TableNewRow para generar de forma automática la clave primaria de la nueva fila.

Volviendo al formulario, quiero poder elegir la tabla que se muestra en él. Para ello se me ocurre poner un ComboBox con la lista de tablas, de forma que al elegir una de ellas se carguen y muestren los datos en el formulario. Así que la dificultad real del formulario se reduce a lo que pasa en el ComboBox. Básicamente, lo que necesito es controlar el evento SelectedIndexChanged para cargar los datos de la tabla elegida y cambiar el título del formulario y algunas etiquetas por los relativos a la tabla. Así que el siguiente paso es ¿qué meto en el ComboBox?

Necesito identificar la tabla, lo que puedo hacer con una enumeración (llamémosla enTablas). Necesito mostrar un nombre en el Combo, por lo que necesito una cadena de texto. Esta cadena puedo usarla para el título del formulario o puede que necesite otras. Ahora junto todo esto en una clase o estructura y, si quiero mostrar las tablas ordenadas en el Combo, puedo implementar la interface IComparable. En fin, algo así:

Private Class MisTablas
    Implements IComparable(Of MisTablas)
    Private _IdTabla As enTablas
    Private _Nombre As String
    Public Sub New(ByVal tabla As enTablas, _
        ByVal NombreTabla As String)
        _IdTabla = tabla
        _Nombre = NombreTabla
    End Sub
    Public ReadOnly Property Nombre() As String
        Get
            Return _Nombre
        End Get
    End Property
    Public ReadOnly Property IdTabla() As enTablas
        Get
            Return _IdTabla
        End Get
    End Property
    Public Function CompareTo(ByVal other As MisTablas) _
        As Integer Implements _
        System.IComparable(Of MisTablas).CompareTo
        Return Me._Nombre.CompareTo(other.Nombre)
    End Function
End Class

En el constructor del formulario puedo llenar una List(of MisTablas) con los datos de todas las tablas y volcarlo al ComboBox (mediante su DataSource, su DisplayMember y su ValueMember). Así, en el SelectedIndexChanged (bueno, hablando con propiedad, en el método que controla ese evento) puedo obtener el ítem seleccionado del Combo, que será del tipo MisTablas, y obtener todos los datos necesarios. Lo siguiente es leer los datos de la tabla.

Como trabajo con DataSet añado al formulario un DataSet genérico, digamos que dsTablas. Este DataSet es el origen de datos del BindingSource bsTablas. En cada cambio de tabla lo que haremos será: desligar la tabla de los controles, limpiando los bindings. A continuación, tiraremos el dataset a la basura y obtendremos otro con los datos nuevos desde la clase de acceso a datos. Por último, volvemos a enlazar todo. O sea, esto:

With Me
    'limpiamos los bindings
    .txtComentarios.DataBindings.Clear()
    .txtDescriptor.DataBindings.Clear()
    'leemos datos
    .dsTablas.Dispose()
    .dsTablas = .TablasMenores.LeerDatos(._TablaElegida)
    'ligamos los controles
    .bsTablas.DataSource = .dsTablas.Tables(0)
    .txtDescriptor.DataBindings.Add(New Binding("text", _
                                 .bsTablas, "Nombre"))
    .txtComentarios.DataBindings.Add(New Binding("text", _
                                 .bsTablas, "Descripcion"))
    .lstNavegacion.DataSource = .bsTablas
    .lstNavegacion.DisplayMember = "Nombre"
End With

TablasMenores es la clase de acceso a datos y LeerDatos es una función que devuelve un DataSet genérico. Como puede verse, recibe un parámetro. Este, del tipo enTablas, indica la tabla que debe leer de la base de datos. Internamente, la clase de acceso a datos dispone de tantos métodos privados de lectura de datos como tablas hay. Cada uno devuelve el DataSet tipado correspondiente. La función pública LeerDatos usa el clásico Select Case para llamar al método privado correspondiente, coge el DataSet tipado que le devuelven y lo manda acá como DataSet genérico.

Así pues, aunque en el formulario tengamos un DataSet genérico, realmente estamos trabajando con el DataSet tipado de la tabla que tengamos elegida. La ventaja que le veo a esto es que el código del formulario queda muy sencillo pero podemos aprovecharnos de todo el código personalizado que queramos meter en los DataSet tipados. En este caso, sólo aprovecho para generar la clave primaria, pero podría tener validación de datos propia o qué se yo.

Como siempre, habrá métodos más simples y elegantes de hacerlo, pero este ha sido el mío.

Un pensamiento en “Un formulario para varias tablas

  1. Luiggy

    interesante, yo tambien estoy haciendo lo mismo, tengo 8 tablas y quiero seleccionarlas con un combobox para hacer las operaciones de listar, modificar, eliminar, actualizar, etc…pero aun no lo consigo, esto trabajando con C#, y BD Postgresql…..desde luego te agradesco por la ayuda..
    saludos

Deja un comentario