none
Utilizar listbox como combobox

    Pregunta

  • hola buenas tardes, tengo la siguiente duda, en mi aplicacion utilizo un combobox en el cual cargo unos datos desde la bd con esta consulta

     

    string cad1 = conexion;
                    //esta consulta ordena los datos alfabeticamente
                    string query1 = "SELECT * from clientes  ORDER BY Cliente";
                    MySqlConnection cnn1 = new MySqlConnection(cad1);
                    MySqlCommand cmd = new MySqlCommand(query1, cnn1);
    
                    MySqlDataAdapter da1 = new MySqlDataAdapter(cmd);
                    DataTable dt1 = new DataTable();
                    da1.Fill(dt1);
                    comboBoxcliente.DataSource = dt1;
                    comboBoxcliente.ValueMember = "idcliente";
                    comboBoxcliente.DisplayMember = "Cliente";
    

     

    lo que querria hacer si se puede es quitas este combo y cargarlos en un listbox que ya lo tengo echo, asi

     

     string cad1 = conexion;
                    //esta consulta ordena los datos alfabeticamente
                    string query1 = "SELECT * from clientes  ORDER BY Cliente";
                    MySqlConnection cnn1 = new MySqlConnection(cad1);
                    MySqlCommand cmd = new MySqlCommand(query1, cnn1);
    
                    MySqlDataAdapter da1 = new MySqlDataAdapter(cmd);
                    DataTable dt1 = new DataTable();
                    da1.Fill(dt1);
                    listBox1.DataSource = dt1;
                    listBox1.ValueMember = "idcliente";
                    listBox1.DisplayMember = "Cliente";
    

     


    el problema me surge cuando tengo que utilizar en otra consulta 

    esto

     cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.SelectedValue));

    me da el siguiente error que con el combobox no me lo da

    No se puede convertir un objeto de tipo 'System.Data.DataRowView' al tipo 'System.IConvertible'.

    lo que quiero es cojer el value esto se puede hacer? alguna idea.

    muchas gracias

    un saludo


    Christian
    • Editado Conexpro jueves, 10 de noviembre de 2011 16:37
    jueves, 10 de noviembre de 2011 16:05

Respuestas

  • es que esto

    cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.ValueMember));

    esta incorrecto debes usar el SelctedValue

    cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.SelectedValue));

     

    el ValueMember se sua para definir que campo sera definido para el valor de la lsita o combo, pero es el SelectedValue quien devolvera el valor elegido por el usuario

     

    No se puede convertir un objeto de tipo 'System.Data.DataRowView' al tipo 'System.IConvertible'

    este es otro problema

    lo que no has comentado es en que evento se produce este problema, sera quizas en el SelectedIndexChanged ?

    prueba definiendo

    listBox1.ValueMember = "idcliente";
    listBox1.DisplayMember = "Cliente";
     
    listBox1.DataSource = dt1;

    o sea el DataSource al final

     

    saludos

     


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    • Editado Leandro TuttiniMVP jueves, 10 de noviembre de 2011 16:35
    • Marcado como respuesta Conexpro jueves, 10 de noviembre de 2011 17:33
    jueves, 10 de noviembre de 2011 16:32
  • valida como comente de usar

    prueba definiendo

    listBox1.ValueMember = "idcliente";
    listBox1.DisplayMember = "Cliente";
     
    listBox1.DataSource = dt1;

    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    • Marcado como respuesta Conexpro jueves, 10 de noviembre de 2011 17:32
    jueves, 10 de noviembre de 2011 17:24

Todas las respuestas

  • Hola Christian,

    No será listbox1.SelectedValue :)

    Saludos,


    phurtado
    jueves, 10 de noviembre de 2011 16:31
    Moderador
  • es que esto

    cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.ValueMember));

    esta incorrecto debes usar el SelctedValue

    cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.SelectedValue));

     

    el ValueMember se sua para definir que campo sera definido para el valor de la lsita o combo, pero es el SelectedValue quien devolvera el valor elegido por el usuario

     

    No se puede convertir un objeto de tipo 'System.Data.DataRowView' al tipo 'System.IConvertible'

    este es otro problema

    lo que no has comentado es en que evento se produce este problema, sera quizas en el SelectedIndexChanged ?

    prueba definiendo

    listBox1.ValueMember = "idcliente";
    listBox1.DisplayMember = "Cliente";
     
    listBox1.DataSource = dt1;

    o sea el DataSource al final

     

    saludos

     


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    • Editado Leandro TuttiniMVP jueves, 10 de noviembre de 2011 16:35
    • Marcado como respuesta Conexpro jueves, 10 de noviembre de 2011 17:33
    jueves, 10 de noviembre de 2011 16:32
  • si lo puse mal pero sigue lanzando el error

    cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.SelectedValue));

    No se puede convertir un objeto de tipo 'System.Data.DataRowView' al tipo 'System.IConvertible'.


    Christian
    jueves, 10 de noviembre de 2011 16:33
  • Hola Christian.

    Puedes pasarnos un poco más de código, aparentemente es indiferente si lo pones antes o después. Lo que si puede influir es el evento donde capturas eso.

    De todas formas te recomiendo algo muy sencillo y que te puede ayudar.

     

    MesageBox.Show(listBox1.SelectedValue.ToString()) antes de 

    cmd1.Parameters.AddWithValue("?cli", Convert.ToInt32(listBox1.SelectedValue)); 

     

    y nos cuentas lo que aparece.

    Saludos,


    phurtado
    jueves, 10 de noviembre de 2011 17:05
    Moderador
  • valida como comente de usar

    prueba definiendo

    listBox1.ValueMember = "idcliente";
    listBox1.DisplayMember = "Cliente";
     
    listBox1.DataSource = dt1;

    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    • Marcado como respuesta Conexpro jueves, 10 de noviembre de 2011 17:32
    jueves, 10 de noviembre de 2011 17:24
  • funciono perfectamente 

    listBox1.ValueMember = "idcliente";
    listBox1.DisplayMember = "Cliente";
     
    listBox1.DataSource = dt1;

    muchas gracias

     


    Christian
    jueves, 10 de noviembre de 2011 17:33
  • Hola Leando,

    La verdad que me parece raro, pero puedes llevar toda la razón. Yo he hecho esta prueba y me funciona perfecta y como ves asigno antes el DataSource que que DisplayMember y ValueMember.

    t.Columns.Add("IdCliente",typeof(int));
                t.Columns.Add("Cliente",typeof(string));
    
                t.Rows.Add(new object[]{1,"Cliente"});
                t.Rows.Add(new object[] { 2, "Nicolas" });
    
                ListBox l = new ListBox();
                l.DataSource = t;
                l.DisplayMember = "Cliente";
                l.ValueMember = "IdCliente";
    
                l.Bounds = new Rectangle(0, 0, 100, 100);
                this.Controls.Add(l);
    
                l.SelectedIndexChanged += (ob, ev) =>
                    {
                        int Cliente = Convert.ToInt32(l.SelectedValue);
                        MessageBox.Show(Cliente.ToString());
                    };
    


    No se, me despista bastante el tema, por eso solicite algo más de código, por que para mí y basando en la prueba que acabo de hacer esto está ok. Otra cosa bien distinta es donde está obteniendo el valor  SelectedValue del ListBox.

    Saludos,


    phurtado
    jueves, 10 de noviembre de 2011 17:37
    Moderador
  • Hola Leandro,

    No entiendo esto. Lo puedes explidar ?

    Saludos,


    phurtado
    jueves, 10 de noviembre de 2011 17:41
    Moderador
  • hola

    hace un timepo realice el mismo analisis

    [Winforms] Como usar el SelectedValue

    la conclusion a la cual llego es que el solo asignar el DataSource este lanza eventos SelectedIndexChanged por cada item que crea, por eso tu ejemplo funciona, porque deberias hacer

    t.Columns.Add("IdCliente",typeof(int));
                t.Columns.Add("Cliente",typeof(string));
    
                t.Rows.Add(new object[]{1,"Cliente"});
                t.Rows.Add(new object[] { 2, "Nicolas" });
    
    ListBox l = new ListBox();

    l.SelectedIndexChanged += (ob, ev) => { int Cliente = Convert.ToInt32(l.SelectedValue); MessageBox.Show(Cliente.ToString()); };

     l.DataSource = t; l.DisplayMember = "Cliente"; l.ValueMember = "IdCliente"; l.Bounds = new Rectangle(0, 0, 100, 100); this.Controls.Add(l);

     

    como veras el evento debe estar asignado previamente

    cuentame ahora si funciona

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    jueves, 10 de noviembre de 2011 17:43
  • Hola Leandro,

    Amigo pues funciona igual entonces es que la carga,sabes donde está en el evento Load del formulario.

    Christian esto es así, de verdad sino te importa responde que esto es importante y se por lo que es. Creo que es un bug que no solo pasa en el ListBox, sino en todos los controles que tienen DataSource, incluido el GridView.

    Saludos,


    phurtado
    jueves, 10 de noviembre de 2011 17:52
    Moderador
  • hola de momento tal cual comento leandro cambiando el datasource funciono, voy a probar tu solucion y comento

     

    un saludo


    Christian
    jueves, 10 de noviembre de 2011 17:59
  • o sea si pones un break aqui

     int Cliente = Convert.ToInt32(l.SelectedValue);

    cuando se asigna el DataSource no se detiene por cada item creado en esa linea ?

    porque si lo haces y usarias el datatable, es donde se produce el problema del invalid cast

     

    la verdad no lo he aplciado con un delegado anonimo como lo has realziado en este ejemplo

    intenta asignando el evento, para ver si es igual el resultado

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    jueves, 10 de noviembre de 2011 18:01
  • Hola,

    Leandro,Christian

    Acabo de ver por lo que es, mirando el código interno y es por el ciclo de vida de la creación de los controles, que era mi sospecha. Mi código funcionaba correcto por que el control no está agregado al formulario, es decir por hacer la prueba lo he creado a mano que es más rápido para mis dedos que dibujarlo :). Una cosa si me extraña el comentario Christian de que con un ComboBox funciona y creo que tampoco, puesto que ambos heredan de ListControl y este el culpable. Es más he dibujado un ComboBox ahora sin dedos y se produce el error si asignas el DataSource antes que el ValueMember. Si alguien se quiere entretener os dejo un código que hay que copiar en el constructor de un formulario, después del InicializeComponent().

    this.Controls.Remove(this.comboBox1);
    
                DataTable t = new DataTable();
                t.Columns.Add("IdCliente", typeof(int));
                t.Columns.Add("Cliente", typeof(string));
    
                t.Rows.Add(new object[] { 1, "Cliente" });
                t.Rows.Add(new object[] { 2, "Nicolas" });
    
    
    
    
    
                this.comboBox1.SelectedIndexChanged += (ob, ev) =>
                {
                    var r = this.comboBox1.SelectedValue;
                    int a = 10;
                };
               
    
                this.comboBox1.DataSource = t;
                this.comboBox1.DisplayMember = "Cliente";
                this.comboBox1.ValueMember = "IdCliente";
    
                
    
                this.Controls.Add(this.comboBox1);
    


    Fijaos en las lineas donde lo quito del formulario y de esta forma funciona correctamente,  si por contra quitamos las lineas

    this.Controls.Remove(this.comboBox1); y lógicamente this.Controls.Add(this.comboBox1); se produce el error y la solución a la chapuza de alguien a quien no quiero nombrar es la que apunta Leandro.

    Algún día me entretendré en documentar esto e intentar aportarlo a http://connect.microsoft.com/, pero es que lleva su tiempo y ando un poco mal de esto.

    Como conclusión y cierre. Siempre que asignemos a un control ComboBox y ListBox un origen de datos de forma manual, debemos de hacer lo que comento Leandro, asignar.

    1. DisplayMember y ValueMember

    2. DataSource.

     


    phurtado
    jueves, 10 de noviembre de 2011 20:11
    Moderador