1

I get an error whenever I try to run my application because instead of getting the real value of comboBox.SelectedValue, I get a DataRowView item.

Here's the code where I'm getting the error:

private void InitDataGridView()
{
    query = "SELECT p.name, p.age FROM Person p INNER JOIN Class c ON p.idC=c.idC WHERE p.id=" 
            + comboBoxClass.SelectedValue;
    command = new SqlCommand(query, connection);
    adapter = new SqlDataAdapter(command);
    datatable = new DataTable();
    adapter.Fill(datatable);
    dataGridViewStudents.DataSource = datatable;
}

comboBoxClass.SelectedValue should return me "idC" since I set DataSource, DisplayMember and (ValueMember -> idC).

idC is the primary key (int).

The ComboBox setting:

comboBoxClass.DataSource = datatable;
comboBoxClass.DisplayMember = "className";
comboBoxClass.ValueMember = "idC";
Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
Alessio Raddi
  • 540
  • 1
  • 6
  • 20
  • You have a SQL injection vulerability. – SLaks Oct 24 '17 at 15:24
  • Can you show how you have set your `ComboBox`? – Salah Akbari Oct 24 '17 at 15:27
  • 1
    Sure! `comboBoxClass.DataSource = datatable; comboBoxClass.DisplayMember = "className"; comboBoxClass.ValueMember = "idC";` – Alessio Raddi Oct 24 '17 at 17:59
  • I think we are looking at the wrong portion of your code. The error is happening in what you wrote, but the core issue seems to be in `comboBoxClass`. Lets have a look at the code that initializes `comboBoxClass` instead so we can understand why your `comboBoxClass.SelectedValue` is a `DataRowViewItem` instead of a `string` or `int` like you are expecting. – blaze_125 Oct 24 '17 at 20:52
  • Changing my query now I can finally see the id, although I still get a `System.Data.SqlClient.SqlException` when the `SqlDataAdapter` tries to fille the DataTable. Right here `adapter.Fill(datatable)` – Alessio Raddi Oct 25 '17 at 12:06

2 Answers2

0

Not binding, or improperly binding the ValueMember can have the exact effect you are describing. As you can see in the below snippet.

Put some break points on the initialization of your ComboBoxand figure out why the ValueMember is not what you need it to be. Then your DataGridView should populate correctly.

using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace BindingToDataTable_46914296
{


    public partial class Form1 : Form
    {
        ComboBox combob = new ComboBox();
        ComboBox combobFail = new ComboBox();
        TextBox txtbx = new TextBox();
        public Form1()
        {
            InitializeComponent();
            InitComboBox();
            InitComboBoxFail();
            InitTxtBx();
        }

        private void InitTxtBx()
        {
            txtbx.Location = new Point(5, 30);
            txtbx.Width = this.Width - 10;
            this.Controls.Add(txtbx);
        }

        /// <summary>
        /// This version works, the proper selected value shows up in the textbox
        /// </summary>
        private void InitComboBox()
        {
            combob.Location = new Point(5,5);
            this.Controls.Add(combob);

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Col1", typeof(string)));
            dt.Columns.Add(new DataColumn("Col2", typeof(string)));
            dt.Columns.Add(new DataColumn("Col3", typeof(string)));
            dt.Columns.Add(new DataColumn("Col4", typeof(Int32)));
            dt.Rows.Add("blah1", "bleh", "bloh", 1);
            dt.Rows.Add("blah2", "bleh", "bloh", 2);
            dt.Rows.Add("blah3", "bleh", "bloh", 3);
            dt.Rows.Add("blah4", "bleh", "bloh", 4);
            combob.DataSource = dt;
            combob.DisplayMember = "Col1";
            combob.ValueMember = "Col4";

            combob.SelectedValueChanged += Combob_SelectedValueChanged;
        }


        /// <summary>
        /// This version DOES NOT work, a DataRowView item appears in the textbox when the selection changes
        /// </summary>
        private void InitComboBoxFail()
        {
            combobFail.Location = new Point(combob.Location.X + combob.Width + 5, 5);
            this.Controls.Add(combobFail);

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Col1", typeof(string)));
            dt.Columns.Add(new DataColumn("Col2", typeof(string)));
            dt.Columns.Add(new DataColumn("Col3", typeof(string)));
            dt.Columns.Add(new DataColumn("Col4", typeof(Int32)));
            dt.Rows.Add("blah1", "bleh", "bloh", 1);
            dt.Rows.Add("blah2", "bleh", "bloh", 2);
            dt.Rows.Add("blah3", "bleh", "bloh", 3);
            dt.Rows.Add("blah4", "bleh", "bloh", 4);
            combobFail.DataSource = dt;
            combobFail.DisplayMember = "Col1";
            //only difference is I am not binding ValueMember

            combobFail.SelectedValueChanged += Combob_SelectedValueChanged;
        }

        private void Combob_SelectedValueChanged(object sender, EventArgs e)
        {
            txtbx.Text = ((ComboBox)sender).SelectedValue.ToString();
        }
    }
}
blaze_125
  • 2,262
  • 1
  • 9
  • 19
0

Ok, I figured out what was wrong in my code. It wasn't neither the comboBox initialization nor dataGridView's but it was completely my fault on writing down a wrong query.

I thank you all for the effort to help me.

Alessio Raddi
  • 540
  • 1
  • 6
  • 20
  • Which query? Query driving which control? If the query was wrong, and you use the query to initialize the control, wouldn't you consider your initialization to be wrong? Either way, glad you fixed it. – blaze_125 Oct 25 '17 at 13:36
  • Yes, you're right actually. The query is a simple select to get classID and className so yes, it was the inizialization. – Alessio Raddi Oct 25 '17 at 13:44