rst
rst

Reputation: 2714

Replace int column in Data Table with combobox for DataGridView (Winforms)

I have a DataTable with some integer values (assume 0 => 'open', 1 => 'proceeding', 2 => 'free' etc.) and in a dgv I want to allow the user to change that value, but with a combobox and with string values. So I created to test this a simple winform app

    public Form1()
    {
        InitializeComponent();

        DataTable dt = new DataTable();
        dt.Columns.Add("test");
        dt.Rows.Add(1);
        dt.Rows.Add(2);

        DataTable source = new DataTable();
        source.Columns.AddRange(new DataColumn[] { new DataColumn("Value", typeof(int)), new DataColumn("Display", typeof(string)) });
        source.Rows.Add(0, "zero");
        source.Rows.Add(1, "one");
        source.Rows.Add(2, "two");

        dataGridView1.DataSource = dt;

        var testTextColumn = new DataGridViewComboBoxColumn();
        testTextColumn.HeaderText = "Text";
        testTextColumn.Name = "testText";
        testTextColumn.DataSource = source;
        testTextColumn.DisplayMember = "Display";
        testTextColumn.ValueMember = "Value";
        dataGridView1.Columns.Add(testTextColumn);
    }

So far so good, I thought I could simply make the test column invisible and only have the testText column visible (in the final app), but how does one combine the to values, i.e. when I change something in the cb update the value of the datatable? I could do it by changeEvents, but that seems rather impractical. Is there some sort of databinding?

Exmple dgv

Upvotes: 0

Views: 699

Answers (2)

JohnG
JohnG

Reputation: 9469

There are three (3) things wrong in your posted code to achieve what you describe.

1-The line of code…

dt.Columns.Add("test");

… is defaulting to a string value. Therefore, the combo box would throw a DataError when you try to bind the “Value” column from the source table. So, you need to specify the int type column in the data. Like…

dt.Columns.Add("test", typeof(int));

2- Before the code set the grids DataSource the code needs to specify that we do NOT want the grid to AutoGenerateColumns. Otherwise, we will end up with two columns. In addition, this grid property is NOT a displayed property in the “Designer.” You will need to set this property BEFORE you add the data source and you need to set this property in your code. Something like…

dataGridView1.AutoGenerateColumns = false;

3- When the code creates the combo box column, it never identifies “which” column in the grids DataSource we want to bind the combo box column to. That is the purpose of the columns DataPropertyName. So, you need to add this line of code in the combo box definition…

testTextColumn.DataPropertyName = "test";

Making these changes, should display only the combo box column.

Upvotes: 1

Nicolas Vieira
Nicolas Vieira

Reputation: 13

creates a cell change event, then takes the number of the row you changed and you have access to the columns with the indexes ...

   private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
            {
                if (dataGridView1.CurrentRow != null)
                {
                    DataGridViewRow dgvRow = dataGridView1.CurrentRow;
                  // do what u want here like 
int teste = Convert.ToInt32(dgvRow.Cells[1].Value);
    }
    }

Upvotes: 0

Related Questions