0

I have a DataGridView that I add a DataGridViewComboBoxColumn to, add values, and set the Value by iterating through the grid rows. The selected Value is the value from another row cell. This is very slow and I'm not sure if I am using best practice or not. For a grid with 3000 rows this takes over two minutes to complete. I have tried iterating via row count and using a foreach loop (in commented code below) with same results. Is there a faster way to do this? Here is my code:

DataGridViewComboBoxColumn cmb = new DataGridViewComboBoxColumn();
        cmb.HeaderText = "New Class";
        cmb.Name = "cmb";

        foreach (DataGridViewRow row in dgClasses.Rows)
        {
            if (row.Cells[0].Value != null)
            {
                cmb.Items.Add(row.Cells[0].Value);
            }
        }

        dgProducts.Columns.Add(cmb);

        for (int i = 0; i < dgProducts.Rows.Count; i++)
        {
            dgProducts.Rows[i].Cells["cmb"].Value = dgProducts.Rows[i].Cells["Class"].Value;
        }

        //foreach (DataGridViewRow row in dgProducts.Rows)
        //{
        //   row.Cells["cmb"].Value = row.Cells["Class"].Value;
        //}
Blaze
  • 1,863
  • 7
  • 23
  • 40
  • Do you have any more detail on why it might be so slow? I was unable to duplicate your problem using simple classes for data sources for the two DGViews - even filling dgClasses with 3000 unique string values in column 0 and filling dgProducts with 3000 objects, each referring to one of the unique classes. Putting a stopwatch in I tested single-thread and a background worker on your posted code and respectively they finished the job in 0.4~ and 0.5~ seconds every trial. – OhBeWise Jan 21 '15 at 19:35
  • The code above is all there is in my method to add the combobox column to the dgProducts grid. If I comment the code after dgProducts.Columns.Add(cmb); the program is very fast as expected. It's definitely the setting of value that's slow. The dgClasses grid only will have a handful of rows so each combobox will not have many values. Less than 20 or so. In a previous method I load the dgProducts grid via ReadXml and then load into a DataView to filter rows. I don't think that would affect later grid iteration would it? – Blaze Jan 22 '15 at 13:34
  • I wouldn't think so, but that's the only real difference between your code and my implementation of it. For example: dgClasses' DataSource is a `List` with only one property that contains strings `{ "Class1", "Class2", ..., "Class20" }` while dgProducts' DataSource is a `List` that contains the same property and a second of string type `{ "Foo1", ..., "Foo3000" }`. Moving dgClasses down to 20 items averages the single-thread- and background-thread-runs at 0.02~ and 0.04~ seconds now. Maybe it has something to do with your DataSource and number of properties? Puzzling. – OhBeWise Jan 22 '15 at 16:05
  • More research I found that setting the DataPropertyName to the other column binds the ComboBox. No need for the row iteration and loads very fast. :) Thanks for your efforts! – Blaze Jan 23 '15 at 13:45
  • Well done! I'm glad you were able to figure out. – OhBeWise Jan 23 '15 at 15:43

1 Answers1

0

I added DataPropertyName and got rid of the looping through the grid rows. Loads very fast now.

private void AddClassCombobox()
    {
        DataGridViewComboBoxColumn cmb = new DataGridViewComboBoxColumn();
        cmb.HeaderText = "New Class";
        cmb.Name = "cmb";
        cmb.DataPropertyName = "Class";  // << Added this

        foreach (DataGridViewRow row in dgClasses.Rows)
        {
            if (row.Cells[0].Value != null)
            {
                cmb.Items.Add(row.Cells[0].Value);
            }
        }

        dgProducts.Columns.Add(cmb);
    }
Blaze
  • 1,863
  • 7
  • 23
  • 40