Ú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.