Llenar un ComboBox

El problema es el siguiente: tengo una tabla con un número de registros reducido (diez o doce como mucho). Quiero poder elegir el registro en un listbox o un combobox. Simple, ¿no? La ventaja del ListControl, tanto ListBox como ComboBox, es que para cada entrada en el mismo puedo tener dos valores, el mostrado (DisplayMember) y el ValueMember. Así, en el ValueMember puedo tener la clave primaria de la tabla, que es internamente con lo que trabajaré, mientras que muestro el campo descriptor que me interese al usuario. No estoy contando nada nuevo.

Una posibilidad sería usar una combinación de DataSet y BindingSource, estableciendo como DataSource del ListControl el BindingSource y seleccionando los campos a mostrar como DisplayMember y ValueMember. Este método lo he usado bastante, la verdad, pero como herramienta de navagación entre registros en la tabla principal que se muestra en el formulario. Me explico:


En rojo aparece señalado un ListBox usado como herramienta de navegación por registros. Lo que busco realmente es el señalado en azul, que presenta una lista de estudios que han producido esas series. El combo muestra el campo Nombre de la tabla Estudio pero también almacena la clave principal, IdEstudio, que es clave externa en la tabla de Series. Lo mismo es aplicable para el combo Valoración (justo encima) y otros. Otro ejemplo quizás más práctico sería un combo con el listado de comerciales en la pantalla de generar nuevo pedido de una aplicación de gestión. Es importante saber qué comercial ha hecho el pedido (sobre todo si van a comisión) y, si son pocos, nos ahorramos el tener que diseñar un formulario de búsqueda o que el comercial tenga que aprenderse su código.

Pero me estoy desviando. Quiero mostrar una tabla (la clave primaria y un campo descriptor) en un ListControl. No voy a trabajar con esa tabla directamente (altas, bajas, modificaciones), así que no necesito tener un dataset zumbando por ahí, así que voy a usar un datareader. La "cosa" quedaría más o menos así:

Dim drDatos As OleDb.OleDbDataReader
Dim cnOleDb As New OleDb.OleDbConnection(MiConexion)
Dim Comando As New OleDb.OleDbCommand("SELECT * FROM " & Tabla, cnOleDb)
Dim tbTabla As New DataTable
cnOleDb.Open()
drDatos = Comando.ExecuteReader()
tbTabla.Load(drDatos, LoadOption.OverwriteChanges)
MiControl.DataSource = tbTabla
MiControl.DisplayMember = tbTabla.Columns.Item(1).Caption
MiControl.ValueMember = tbTabla.Columns.Item(0).Caption
drDatos.Close()
cnOleDb.Close()

Donde Tabla es el nombre de la tabla en cuestión, MiConexion es la cadena de conexión empleada y se asume que el campo 0 de la tabla es la clave primaria (ValueMember) y el campo 1 es el campo descriptor que vamos a mostrar y MiControl es el ListControl (da igual que sea un ListBox o un ComboBox) que vamos a rellenar. El código del ejemplo es un poco "de andar por casa". Lo suyo sería que el objeto conexión estuviera en un bloque Using y falta la gestión de errores, pero sirve como base.

Como este procedimiento, es decir, llenar un ComboBox o ListBox con datos de una tabla a partir de un DataReader, lo utilizo bastante, me sirvió para hacerme mi primera clase en Visual Basic 2005 (y comprender cómo funcionan), así como para probar el tema de las sobrecargas. Es mi idea comentar esa primera clase en próximas entradas, por puro y sencillo egocentrismo (tampoco es que me vaya a leer nadie, claro).

Nos vemos en el Forlon.

5 comentarios para “Llenar un ComboBox

  1. Me parece muy bueno tu codigo, he buscado un codigo como el tuyo, sabes eres bueno.

    Gracias por tu aporte y que sigas aportando mas!!!

  2. Por razones extrañas, necesitaba ocupar el valor seleccionado del Combo en un Form y descubrí que no se puede (propiedad SelectedItem) con un combo asociado a una dataset, datatable. ya que el form “se cae”. Generalmente se ocupa el SelecteValue y funciona pero esta vez necesitaba el SelecteItem. Creo que es un error grave de Visual Studio (2010 con Visual Basic .Net en mi caso). Así que como emergencia recuperé el SelectedValue y tuve que hacer una nueva llamada a la tabla para buscar la descripción, misma que estaba en el Combo. Alguien tiene una solución más sencilla?

  3. SelectedItem te devuelve el objeto seleccionado. Si tu datasource es un datatable, este objeto será un datarowview, una vista sobre la fila de la tabla. Pues obtener cualquier campo de ella o bien obtener la row directamente y trabajar con ella. Algo del tipo Trycast(mComboBox.SelectedItem, DataRowView).

    El valor mostrado lo puedes obtener, si no me equivoco, por la propiedad Text.

  4. Si gracias. Después de mucho probar y leer por ahí, descubrí que para datos enlazados, utilizando la propiedad Text obtengo el valor seleccionado de la lista. Un poco extraño, pero bueno son las rarezas de Visual Studio, y tal como dices SelectedItem devuelve un datarowview.

Deja un comentario