0

I have fairly large (4700 lines) Windows Forms application that I wrote to coordinate three departments in my manufacturing plant. I have many combo boxes throughout the application and all work perfectly, but I have one combo box who's paint works fine on load, but once you change tabs and come back the combobox is frozen. Please note: this is the order of objects Form1 > TableLayoutPanel > TabControl > TabPage > TableLayoutPanel > ComboBox.

On Load: enter image description here

After changing tabs (it is painted with whatever background of the tab i just clicked off of): enter image description here

The only way to fix this is to close the application and reopen. As long as I stay on the tab the control works perfectly the entire time.

Here is how I load the data for the combo box:

private void LoadFGPN()
    {
        SqlConnection con = new SqlConnection(Properties.Resources.Tef7_Conn);

        SqlDataAdapter da;
        DataTable dt = new DataTable();
        StringBuilder sql = new StringBuilder();
        sql.Append("SELECT DISTINCT(material) FROM [TEF7].[CM].[ALLPartNumbers] WHERE material LIKE '_____7______-6RP' OR material LIKE '_____4______-6RP' OR material LIKE '_________8__-6ML' OR material LIKE '_________[0-7,9]__-6ML'");

        da = new SqlDataAdapter(sql.ToString(), con);
        da.Fill(dt);

        if (cbFGPN.DataSource == null)
        {
            cbFGPN.DataSource = dt;
        }
        else
        {
            cbFGPN.DataSource = null;
            cbFGPN.DataSource = dt;
        }
        cbFGPN.ValueMember = "material";
        cbFGPN.DisplayMember = "material";
    } //loads finished good combo box on kanban

What I've tried:
* SelectionChangeCommitted event and adding .Refresh() and .Invalidate() / .Update() individually with no success.
* Draw Mode property of the combo box is set to Normal
* winforms tabcontrol
* suspend paint
* force paint event

I'm stumped. Any ideas on how to fix this?

EDIT: Just to be ridiculous I tried the following with no success. The control stays hidden.

if (tcMain.SelectedIndex == 0)
        {
            cbFGPN.Hide();
            LoadPreOrderGridview("eKanban", null, null, null, null, null); //loads preorder gridview
            LoadFGPN();
            LoadRawPN();
            cbFGPN.Show();
            tlpMain.Refresh();
            tcMain.Refresh();
            tpKanban.Refresh();
            tlpKanban.Refresh();
            pnKanban.Refresh();
            cbFGPN.Refresh();
        }

1 Answers1

2

Solution to this is very easy. Just put Value and Display member code before you assign datasource to combobox.

so instead of:

if (cbFGPN.DataSource == null)
{
    cbFGPN.DataSource = dt;
}
else
{
    cbFGPN.DataSource = null;
    cbFGPN.DataSource = dt;
}
cbFGPN.ValueMember = "material";
cbFGPN.DisplayMember = "material";

Do:

cbFGPN.ValueMember = "material";
cbFGPN.DisplayMember = "material";

if (cbFGPN.DataSource == null)
{
    cbFGPN.DataSource = dt;
}
else
{
    cbFGPN.DataSource = null;
    cbFGPN.DataSource = dt;
}

Why does it happens?

When you want to assign DisplayMember and ValueMember of already populated element it goes to every object in that element and write to it what to use as display and what as value member and every time he enters object which is already there it fires few events (like validated, validating, textChanged, dataSourceChanged and others (it depends on element)) and when you need to fire like 10 events * 4700 rows it "freezes" - take too long to finish.

When you assign Displaymember and ValueMember before datasource and then change datasource only one time, all objects inherits Display and Value member property and doesn't fire events so it doesn't freeze.

Important note: As i have tested and worked with this works everywhere expect checkedListBox and ListBox. For some reason it doesn't allow me to assign Display and Value members before i assign datasource.

Aleksa Ristic
  • 2,394
  • 3
  • 23
  • 54
  • Thank you very much! Only change I made is adding the value and display members into the if statement i already had.
    if (cbFGPN.DataSource == null) { cbFGPN.DataSource = dt; cbFGPN.ValueMember = "material"; cbFGPN.DisplayMember = "material"; } else { cbFGPN.ValueMember = "material"; cbFGPN.DisplayMember = "material"; cbFGPN.DataSource = dt; }
    – FullStackDeveloper Sep 06 '18 at 13:06