Llenar un ComboBox IV

Última entrega. Por fin lo útil: llenar el Combo, el ListBox y alguna cosita más.

El corazón de la clase son dos métodos privados que son los que rellenan el ListControl (ya sea un ListBox o un ComboBox). Ambos reciben como parámetros el control que se va a rellenar, el nombre de la tabla origen, los dos campos con los que vamos a rellenar el control (indentificados por su índice en la colección de columnas de la tabla, o su posición, para entendernos), una sentencia WHERE para ajustar la consulta y una sentencia de ordenación, ambas sin las palabras reservadas WHERE y ORDER BY. El método para OleDB es el siguiente:

Private Function RellenarComboOleDB( _
        ByVal MiControl As System.Windows.Forms.ListControl, _
        ByVal Tabla As String, ByVal ClavePrincipal As Integer, _
        ByVal CampoDescriptor As Integer, _
        ByVal SentenciaWhere As String, _
        ByVal SentenciaOrderBy As String) As Boolean
    Dim drDatos As OleDb.OleDbDataReader
    Dim Comando As New OleDb.OleDbCommand("SELECT * FROM " & Tabla, _
                                    Me._cnOleDb)
    Dim tbTabla As New DataTable
    Dim deVuelta As Boolean
    Try
        If SentenciaWhere.Length > 0 Then
            Comando.CommandText = "SELECT * FROM " & Tabla _
                    & " WHERE " & SentenciaWhere
        End If
        If SentenciaOrderBy.Length > 0 Then
            Comando.CommandText = Comando.CommandText & _
                    " ORDER BY " & SentenciaOrderBy
        End If
        drDatos = Comando.ExecuteReader()
        tbTabla.Load(drDatos, LoadOption.OverwriteChanges)
        MiControl.DataSource = tbTabla
        MiControl.DisplayMember = _
            tbTabla.Columns.Item(CampoDescriptor).Caption
        MiControl.ValueMember = _
            tbTabla.Columns.Item(ClavePrincipal).Caption
        drDatos.Close()
        deVuelta = True
    Catch NoConexion As InvalidOperationException
        'Error del Comado.ExecuteReader
        deVuelta = False
        Throw NoConexion
    Catch NoConexion As Exception
        deVuelta = False
        Throw NoConexion
    Finally
        Comando = Nothing
        tbTabla = Nothing
    End Try
    Return deVuelta
End Function

Para SQL es similar, pues sólo cambian el nombre (RellenarComboSQL), el tipo de objeto DataReader, el Command y la conexión utilizada, es decir, en vez de:

Dim drDatos As OleDb.OleDbDataReader
Dim Comando As New OleDb.OleDbCommand("SELECT * FROM " & Tabla, _
        Me._cnOleDb)

Tendríamos:

Dim drDatos As SqlClient.SqlDataReader
Dim Comando As New SqlClient.SqlCommand("SELECT * FROM " & Tabla, _
        Me._cnSQL)

Como métodos públicos tenemos dos variantes, donde jugamos con la sobrecarga de operadores. El primero, que se muestra a continuación, es el principal. En él asumimos que la conexión ya está abierta, bien porque hemos llamado previamente al método Conectar, bien porque le hemos pasado un objeto conexión a través de la propiedad ConexionOleDB o ConexionSQL. Como puede verse, los parámetros que recibe son los mismos que reciben los métodos privados vistos antes, con la salvedad de que, salvo el control y el nombre de la tabla, los demás son opcionales. En lo que a mí respecta, la situación más habitual para la que estoy usando esta clase es para rellenar combos con tablas que no tienen más de 10-15 registros y tres campos: por orden, IdTabla, Nombre y Descripción, siendo los dos primeros los campos a mostrar en el combo. De ahí los valores por defecto de los parámetros opcionales.

Lo que hace el método es identificar con qué base de datos estamos tratando y llamar al método privado correspondiente, pasándole por parámetro lo que a él le ha llegado.

''' <summary>
''' Rellena un ListControl con un campo descriptor 
''' y la clave principal de una tabla
''' para usarlo como clave externa en otra tabla.
''' </summary>
''' <param name="MiControl">ListControl (Combo, ListBox)
''' que se va a rellenar</param>
''' <param name="Tabla">Nombre de la tabla a rellenar</param>
''' <param name="ClavePrincipal">Número del campo Clave Principal
''' en la tabla (por defecto, 0)</param>
''' <param name="CampoDescriptor">Número del campo descriptor
''' usado como DisplayMember del Combo (por defecto, el 1)</param>
''' <param name="SentenciaWhere">Sentencia WHERE de la selección
''' SQL (sin el WHERE). Puede incluir más opciones, como ORDER BY.
''' No se realiza ninguna comprobación sobre la sentencia</param>
''' <param name="OrdenarPor">Sentencia ORDER BY, si la hay.</param>
''' <returns>True operación completada, False si se ha producido
''' un error</returns>
''' <remarks>Hay que haber pasado previamente la cadena de
''' conexión a la propiedad CadConexion y abrir la conexión
''' con el método Conectar antes de llamar a este método
''' y llamar a Desconectar al finalizar.</remarks>
Public Function RellenarCombo(ByVal MiControl As _
        System.Windows.Forms.ListControl, _
        ByVal Tabla As String, _
        Optional ByVal ClavePrincipal As Integer = 0, _
        Optional ByVal CampoDescriptor As Integer = 1, _
        Optional ByVal SentenciaWhere As String = "", _
        Optional ByVal OrdenarPor As String = "") As Boolean
    Dim deVuelta As Boolean
    'Según el tipo de base de datos al que estemos conectados, 
    'llama a una u otra función que rellenarán el combo.
    Try
        Select Case _BDD
            Case QueBase.Access
                deVuelta = Me.RellenarComboOleDB(MiControl, _
                    Tabla, ClavePrincipal, CampoDescriptor, _
                    SentenciaWhere, OrdenarPor)
            Case QueBase.SQL
                deVuelta = Me.RellenarComboSQL(MiControl, _
                    Tabla, ClavePrincipal, CampoDescriptor, _
                    SentenciaWhere, OrdenarPor)
            Case Else
                deVuelta = False
                Throw New ApplicationException( _
                    "Tipo de base de datos desconocido o no establecido")
        End Select
    Catch NoConexion As Exception
        Throw NoConexion
        deVuelta = False
    End Try
    Return deVuelta
End Function

La otra variante de RellenarCombo no necesita tener una conexión abierta, sino que se preocupa él mismo de abrirla y cerrarla. Para ello, tiene un parámetro adicional que es la cadena de conexión. Así, si sólo vamos a llenar un ListControl, podemos usar este método y condensarlo todo en una única llamada, mientras que usaremos el anterior si vamos a aprovechar la conexión abierta para más cosas (llenar varios combos y listboxes, llenar algún dataset…).

Public Function RellenarCombo(ByVal MiControl As _
        System.Windows.Forms.ListControl, _
        ByVal Tabla As String, _
        ByVal CadenaConexion As String, _
        Optional ByVal ClavePrincipal As Integer = 0, _
        Optional ByVal CampoDescriptor As Integer = 1, _
        Optional ByVal SentenciaWhere As String = "", _
        Optional ByVal OrdenarPor As String = "") As Boolean
    Dim DeVuelta As Boolean
    Try
        Me.CadConexion = CadenaConexion
        DeVuelta = Me.Conectar
        If DeVuelta Then
            DeVuelta = Me.RellenarCombo(MiControl, _
                Tabla, ClavePrincipal, CampoDescriptor, _
                SentenciaWhere, OrdenarPor)
        End If
    Catch NoConexion As Exception
        DeVuelta = False
        Throw NoConexion
    Finally
        Me.Desconectar()
    End Try
    Return DeVuelta
End Function

Y eso es todo. No es ninguna maravilla, pero me es útil. Si a alguien le sirve, pues mejor.

*Ejem* Bueno, no es todo. RellenarCombo presenta 4 sobrecargas (variantes) y aquí sólo he puesto dos de ellas. Las otras dos son iguales, pero cambiando el ListControl por un DataGridViewComboBoxColumn, o sea, la variante del ComboBox para DataGridView. Cambiando ese pequeño detalle, son exactamente iguales y, por supuesto, llevan sus métodos privados correspondientes (RellenarComboDataGridOleDB y RellenarComboDataGridSQL, de momento). Y, ahora, sí, eso es to… to… todo, amigos.

Deja un comentario

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.