Search code examples
c#winformscomboboxbackgroundworker

winform combobox clear empty entries


I have an Problem with the WinForms-Combobox. I populate the Box with a BackgroundWorker. When I call comboBox.Items.Clear() the dropdownlist of the combobox has still a size like there are items in the combobox. But there is no Text. When i run the backgroundworker to fill the combobox again, there are 2 Entries for each item. When i clear the list and run it again there are 3 and so on. Seems like they are not getting cleared at all.

private void buttonConnect_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker.IsBusy)
            {
                var sqlConnectionStringBuilder = new SqlConnectionStringBuilder();
                sqlConnectionStringBuilder.DataSource = textBoxDataSource.Text;
                sqlConnectionStringBuilder.UserID = textBoxUserId.Text;
                sqlConnectionStringBuilder.Password = textBoxPassword.Text;
                sqlConnectionStringBuilder.InitialCatalog = textBoxInitialCatalog.Text;

                backgroundWorker.WorkerReportsProgress = true;
                backgroundWorker.DoWork += Read;
                backgroundWorker.ProgressChanged += Populate;
                backgroundWorker.RunWorkerCompleted += Finish;
                backgroundWorker.RunWorkerAsync(sqlConnectionStringBuilder);
            }
        }

private void Read(object sender, DoWorkEventArgs e)
        {
            var sqlConnectionStringBuilder = e.Argument as SqlConnectionStringBuilder;

            using (var context = new HadesContext(sqlConnectionStringBuilder.ConnectionString))
            {
                var items = context.Items.ToList();

                for (int i = 0; i < items.Count; i++)
                    backgroundWorker.ReportProgress(0, items[i].Name}                
            }
        }

private void Populate(object sender, ProgressChangedEventArgs e)
        {
            progressBarProgress.Value = e.ProgressPercentage;
            comboBoxItems.Items.Add(e.UserState.ToString());
        }

Solution

  • Your problem is this line:

    backgroundWorker.DoWork += Read;
    

    Every time you press the button you register an additional event! So the second time you press it, the first event is fired and after it has finished reading the data the second event (which you just registered) is fired and it reads the data again. This is why your data is multiplied at each click to the amount of your clicks.

    The solution would be either to unregister it again, when the reading job is finished or (which I would prefer) to put the event registration into the constructor of the Form which is called once at the start:

    public Form1()
    {
        InitializeComponent();
    
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.DoWork += Read;
        backgroundWorker.ProgressChanged += Populate;
        backgroundWorker.RunWorkerCompleted += Finish;
    }
    

    Leave only the lines for the SqlConnectionStringBuilder and the call of the RunWorkerAsync in the button click event:

    private void buttonConnect_Click(object sender, EventArgs e)
    {
        if (!backgroundWorker.IsBusy)
        {
            var sqlConnectionStringBuilder = new SqlConnectionStringBuilder();
            sqlConnectionStringBuilder.DataSource = textBoxDataSource.Text;
            sqlConnectionStringBuilder.UserID = textBoxUserId.Text;
            sqlConnectionStringBuilder.Password = textBoxPassword.Text;
            sqlConnectionStringBuilder.InitialCatalog = textBoxInitialCatalog.Text;
    
    
            backgroundWorker.RunWorkerAsync(sqlConnectionStringBuilder);
        }
    }
    

    EDIT:

    As for the weird dropdown length of the ComboBox you can set the ComboBox.IntegralHeight property to false after you have cleared the item list. This will result in the small dropdown. Disclaimer is that at the next fill it will not open entirely but with a scroll bar. May be this answer can help you further