none
ComBox en DatagridView? C# - SQL Server RRS feed

  • Pregunta

  • Hola

    Tengo en SQL Server las tablas:

    Estados:

    int id_estado (PF)

    varchar (50) descripcion 

    Ventas

    int id_venta (PF)

    datetime fecha

    int id_estado (FK)

    En un dategridviw en c# muestro Select id_venta, E.descripcion from Venta V inner join Estados E on E.id_estado = V.id_estado

    Si quiero modificar el estado desde el datagridview directamente, me deja ponerle 1 o 2 o 3, pero no me deja ponerle estado "Vendido" o "Pendiente".

    En vez de poner 1 o 2 o 3 para modificar el estado desde el datagridview, se puede desplegar un combobox con la descripcion de cada estado y poder modificar la venta ingresando la descripcion del estado en vez el id_estado?



    A

    domingo, 4 de octubre de 2020 3:54

Respuestas

  • Hola Yan Eric

    Pido disculpas porque el código que te pasé está MAL casi todo, y te agradezco porque por este post tuyo y otro de hace un rato de Christian (problemas muy similares) aprendí algo muy importante, que lo investigué gracias a ustedes.

    Te paso el código bien (lo probé con tu BD en mi SSMS) y luego te comento los detalles.

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Windows.Forms;
    
    namespace WindowsFormsAppModifyByComboBox
    {
        public partial class Form1 : Form
        {
            private ComboBox combo;
            private SqlConnection conn;
    
            public Form1()
            {
                InitializeComponent();            
            }
    
            private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                combo = e.Control as ComboBox;
    
                combo.SelectionChangeCommitted -= new EventHandler(combo_SelectionChangeCommitted);
    
                combo.SelectionChangeCommitted += new EventHandler(combo_SelectionChangeCommitted);
            }
    
            private void combo_SelectionChangeCommitted(object sender, EventArgs e) 
            {
                int id_estado = (int)combo.SelectedValue;
    
                string query2 = "UPDATE Ventas SET id_estado = " + id_estado.ToString() + " WHERE id_venta = "
                    + dataGridView1.CurrentRow.Cells[0].Value.ToString();
                conn.Open();
                SqlCommand command2 = new SqlCommand(query2, conn);
                command2.ExecuteNonQuery();
                conn.Close();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                conn = new SqlConnection(@"Server=PABLOMARTY-PC\SQLEXPRESS;Database=VENTAS;Trusted_Connection=True;");
                dataGridView1.AutoGenerateColumns = false;            
                string query = "SELECT id_venta, id_estado FROM Ventas";
                SqlCommand command = new SqlCommand(query, conn);
                DataTable table = new DataTable();
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                adapter.Fill(table);
                Id_Venta.DataGridView.DataSource = table;
                Id_Venta.DataPropertyName = "id_venta";
    
                string query2 = "SELECT * FROM Estados";
                SqlCommand command2 = new SqlCommand(query2, conn);
                DataTable table2 = new DataTable();
                SqlDataAdapter adapter2 = new SqlDataAdapter(command2);
                adapter2.Fill(table2);
    
                Descripcion.DataGridView.DataSource = table;
                Descripcion.DataPropertyName = "id_estado";
                Descripcion.DataSource = table2;
                Descripcion.ValueMember = "id_estado";
                Descripcion.DisplayMember = "descripcion";            
            }
        }
    }
    

    La consulta SQL de la tabla principal debería seleccionar los campos sin ningún JOIN, porque con sólo tener el valor de la FK obtenemos el string en la columna ComboBox.

    Para eso, 1° cargamos los items con sus values a la columna:

    Descripcion.DataSource = table2;  // SELECT * FROM Estados

    Descripción.ValueMember = "id_estado";  // el Id o PK de la tabla detalle

    Descripcion.DisplayMember = "descripcion";  // el string o item

    Lo anterior asigna datos en lo que es el ComboBox independientemente de las demás columnas

    Ahora, para que "enganche" el valor de la FK de la tabla principal con el ValueMember del ComboBox y muestre el string correspondiente:

    Descripcion.DataGridView.DataSource = table;  // SELECT * FROM Ventas

    Descripcion.DataPropertyName = "id_estado"; // la FK de la tabla principal

    Con lo anterior se vincula los datos del DataGridView y su columna FK id_estado con el value del ComboBox para que coincidan y muestre el item correcto.

    Si cambias la selección del ComboBox automáticamente se guarda (con la consulta y el SqlCommand) el nuevo valor de la FK (id_estado) de la tabla principal. En el método del evento EditingControlShowing (que se produce al manipular el ComboBox), se agrega el método del evento SelectionChangeCommitted del mismo, que una vez realizado el cambio ejecuta el SQL.

    Gracias por ayudarme a aprender y compartir con los demás.

    Saludos

    Pablo

    • Marcado como respuesta Eric_96 lunes, 12 de octubre de 2020 12:10
    jueves, 8 de octubre de 2020 1:46

Todas las respuestas

  • Hola Yan Eric

    Tu DataGridView va enlazado a datos, como un DataTable? Creo que si no va, es más fácil hacer lo que pedis.

    Pablo

    domingo, 4 de octubre de 2020 14:07
  • Hola Yan Eric

    Al fin lo pude resolver, enlazado a datos y todo. Este es el código. Habría que poner un DataGridView en el Form, con 2 columnas, una TextBox (llamada Id_Venta) y la otra ComboBox (llamada Descripcion). En mi ejemplo, los Estados , que se los paso a los Items de la columna ComboBox, son PEDIDO, PENDIENTE, y ENTREGADO. Podes probar con tus tablas, poniendo datos variados. El DataGridView te mostrará el id_venta y la descripción de cada venta, en las 2 columnas. Cuando modificas con el ComboBox un estado, automáticamente se hace un UPDATE del campo id_estado en la tabla Ventas, y al iniciar la aplicación otra vez ese cambio ya estará. Tendrías que asignar el método del EditingControlShowing en el cuadro de Propiedades.

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Windows.Forms;
    
    namespace WindowsFormsAppModifyByComboBox
    {
        public partial class Form1 : Form
        {
            private ComboBox combo;
            private SqlConnection conn;
    
            public Form1()
            {
                InitializeComponent();            
            }
    
            private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                combo = e.Control as ComboBox;
    
                combo.SelectionChangeCommitted -= new EventHandler(combo_SelectionChangeCommitted);
    
                combo.SelectionChangeCommitted += new EventHandler(combo_SelectionChangeCommitted);
            }
    
            private void combo_SelectionChangeCommitted(object sender, EventArgs e) 
            {
                string query1 = "SELECT id_estado FROM Estados WHERE descripcion = '" + combo.SelectedItem.ToString() + "'";
                SqlCommand command1 = new SqlCommand(query1, conn);
                conn.Open();
                SqlDataReader reader = command1.ExecuteReader();
                reader.Read();
                int id_estado = reader.GetInt32(0);
                reader.Close();
    
                string query2 = "UPDATE Ventas SET id_estado = " + id_estado.ToString() + " WHERE id_venta = "
                    + dataGridView1.CurrentRow.Cells[0].Value.ToString();
                SqlCommand command2 = new SqlCommand(query2, conn);
                command2.ExecuteNonQuery();
                conn.Close();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                conn = new SqlConnection(@"Server=PABLOMARTY-PC\SQLEXPRESS;Database=VENTAS;Trusted_Connection=True;");
                Descripcion.Items.AddRange("PEDIDO", "PENDIENTE", "ENTREGADO");
                dataGridView1.AutoGenerateColumns = false;
                string query = "SELECT V.id_venta, V.id_estado, E.descripcion FROM Ventas V INNER JOIN Estados E ON V.id_estado = E.id_estado";
                SqlCommand command = new SqlCommand(query, conn);
                DataTable table = new DataTable();
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                adapter.Fill(table);
                Id_Venta.DataGridView.DataSource = table;
                Id_Venta.DataPropertyName = "id_venta";
                
                Descripcion.DataGridView.DataSource = table;
                Descripcion.DataPropertyName = "descripcion";
                Descripcion.ValueMember = "id_estado";
                Descripcion.DisplayMember = "descripcion";
            }
        }
    }
    

    Espero que te sea útil.

    Saludos

    Pablo

    domingo, 4 de octubre de 2020 14:26
  • Hola Yan, 

      

    ¿Alguna novedad sobre la consulta realizada? 

    Cualquier duda referente a productos Microsoft, puedes consultarnos. Es un gusto informarte. 

    Gracias por usar los foros de MSDN.  

    Eric Ruiz

    ____________________________  

     

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde.  

    Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft.   

    Este contenido es proporcionado "tal cual" y no implica ninguna responsabilidad de parte de Microsoft. 

    lunes, 5 de octubre de 2020 16:21
    Moderador
  • Hola Yan Eric

    Pido disculpas porque el código que te pasé está MAL casi todo, y te agradezco porque por este post tuyo y otro de hace un rato de Christian (problemas muy similares) aprendí algo muy importante, que lo investigué gracias a ustedes.

    Te paso el código bien (lo probé con tu BD en mi SSMS) y luego te comento los detalles.

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Windows.Forms;
    
    namespace WindowsFormsAppModifyByComboBox
    {
        public partial class Form1 : Form
        {
            private ComboBox combo;
            private SqlConnection conn;
    
            public Form1()
            {
                InitializeComponent();            
            }
    
            private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                combo = e.Control as ComboBox;
    
                combo.SelectionChangeCommitted -= new EventHandler(combo_SelectionChangeCommitted);
    
                combo.SelectionChangeCommitted += new EventHandler(combo_SelectionChangeCommitted);
            }
    
            private void combo_SelectionChangeCommitted(object sender, EventArgs e) 
            {
                int id_estado = (int)combo.SelectedValue;
    
                string query2 = "UPDATE Ventas SET id_estado = " + id_estado.ToString() + " WHERE id_venta = "
                    + dataGridView1.CurrentRow.Cells[0].Value.ToString();
                conn.Open();
                SqlCommand command2 = new SqlCommand(query2, conn);
                command2.ExecuteNonQuery();
                conn.Close();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                conn = new SqlConnection(@"Server=PABLOMARTY-PC\SQLEXPRESS;Database=VENTAS;Trusted_Connection=True;");
                dataGridView1.AutoGenerateColumns = false;            
                string query = "SELECT id_venta, id_estado FROM Ventas";
                SqlCommand command = new SqlCommand(query, conn);
                DataTable table = new DataTable();
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                adapter.Fill(table);
                Id_Venta.DataGridView.DataSource = table;
                Id_Venta.DataPropertyName = "id_venta";
    
                string query2 = "SELECT * FROM Estados";
                SqlCommand command2 = new SqlCommand(query2, conn);
                DataTable table2 = new DataTable();
                SqlDataAdapter adapter2 = new SqlDataAdapter(command2);
                adapter2.Fill(table2);
    
                Descripcion.DataGridView.DataSource = table;
                Descripcion.DataPropertyName = "id_estado";
                Descripcion.DataSource = table2;
                Descripcion.ValueMember = "id_estado";
                Descripcion.DisplayMember = "descripcion";            
            }
        }
    }
    

    La consulta SQL de la tabla principal debería seleccionar los campos sin ningún JOIN, porque con sólo tener el valor de la FK obtenemos el string en la columna ComboBox.

    Para eso, 1° cargamos los items con sus values a la columna:

    Descripcion.DataSource = table2;  // SELECT * FROM Estados

    Descripción.ValueMember = "id_estado";  // el Id o PK de la tabla detalle

    Descripcion.DisplayMember = "descripcion";  // el string o item

    Lo anterior asigna datos en lo que es el ComboBox independientemente de las demás columnas

    Ahora, para que "enganche" el valor de la FK de la tabla principal con el ValueMember del ComboBox y muestre el string correspondiente:

    Descripcion.DataGridView.DataSource = table;  // SELECT * FROM Ventas

    Descripcion.DataPropertyName = "id_estado"; // la FK de la tabla principal

    Con lo anterior se vincula los datos del DataGridView y su columna FK id_estado con el value del ComboBox para que coincidan y muestre el item correcto.

    Si cambias la selección del ComboBox automáticamente se guarda (con la consulta y el SqlCommand) el nuevo valor de la FK (id_estado) de la tabla principal. En el método del evento EditingControlShowing (que se produce al manipular el ComboBox), se agrega el método del evento SelectionChangeCommitted del mismo, que una vez realizado el cambio ejecuta el SQL.

    Gracias por ayudarme a aprender y compartir con los demás.

    Saludos

    Pablo

    • Marcado como respuesta Eric_96 lunes, 12 de octubre de 2020 12:10
    jueves, 8 de octubre de 2020 1:46