Wednesday, October 28, 2020

Separating Combo Boxes with Similar Data

A situation came up where a Windows Forms application required 2 combo boxes filled with customer IDs.  A caption of that form is shown below, where a user must select “From Customer ID” and “To Customer ID”.  Since both combo boxes were populated from the same data column, the natural thing to do was to use the same code for filling both with the same data.  However, this caused an undesirable effect.  When the user selected the “From Customer ID”, the “To Customer ID” was automatically populated with the same value. 

 

To resolve this problem, 2 separate DataTable objects must be used, dtFrom and dtTo.  Although both objects are populated using the same method (dm.GetCustomerIDNames()), keeping the objects separate will prevent one control selection from effecting the other control.  See sample code shown below.

 

 

 

        private void FillCustomerIDs()

        {

            Cursor.Current = Cursors.WaitCursor;  //Produces a "wait cursor" while data is loading

 

            //Must have 2 separate instances for the data method. 

            //DataTables must also be kept separate to prevent issues with binding

            //Data must NOT be cached, must be retrieved directly from the DB for each call. 

            //Otherwise all comboboxes will bind to the same datasource and to each other.

 

            DataTable dtFrom = dm.GetCustomerIDNames();

            FillFromCustomer(dtFrom);

 

            DataTable dtTo = dm.GetCustomerIDNames();

            FillToCustomer(dtTo);

        }

 

 

        private void FillFromCustomer(DataTable dtFrom)

        {

            AutoCompleteStringCollection acsFrom = new AutoCompleteStringCollection();

 

            foreach (var rec in dtFrom.AsEnumerable())

                acsFrom.Add(rec.ItemArray[0].ToString());

 

            cbFromCustomerID.AutoCompleteCustomSource = acsFrom;

            cbFromCustomerID.AutoCompleteMode = AutoCompleteMode.SuggestAppend;

            cbFromCustomerID.AutoCompleteSource = AutoCompleteSource.CustomSource;

 

            cbFromCustomerID.DataSource = dtFrom;

            cbFromCustomerID.DisplayMember = "ID";

            cbFromCustomerID.ValueMember = "Name";

            cbFromCustomerID.SelectedIndex = -1;    //Forces a blank item in the comboBox

        }

 

 

        private void FillToCustomer(DataTable dtTo)

        {

            AutoCompleteStringCollection acsTo = new AutoCompleteStringCollection();

 

            foreach (var rec in dtTo.AsEnumerable())

                acsTo.Add(rec.ItemArray[0].ToString());

 

            cbToCustomerID.AutoCompleteCustomSource = acsTo;

            cbToCustomerID.AutoCompleteMode = AutoCompleteMode.SuggestAppend;

            cbToCustomerID.AutoCompleteSource = AutoCompleteSource.CustomSource;

 

            cbToCustomerID.DataSource = dtTo;

            cbToCustomerID.DisplayMember = "ID";

            cbToCustomerID.ValueMember = "Name";

            cbToCustomerID.SelectedIndex = -1;

        }