Rick Carter
Rick Carter

Reputation: 25

c# confirm each combobox has a unique value selected

I have a winform with a group of comboboxes, all of the comboboxes with the same list items in them.

I need a way to confirm that when the user is done selecting a value in each box that they only selected each list value once.

Ex: cbox1 cbox2 cbox 3 Item A Item B Item A (this needs to flag an error since Item A is already selected in cbox1)

I was thinking trying to use the selectedvaluecommited action (as after i populate the list I change the selected index to -1 so they all show "empty" to start) but the loop to make it work seems to be eluding me.

background: this is choosing fields to build a spreadsheet and the user needs to choose the field order.

Upvotes: 2

Views: 1101

Answers (3)

Rupesh
Rupesh

Reputation: 342

If it is possible to have different UI design then my suggestion goes as under:

Alternative UI Design - A

  1. Create One ListBox ListFieldsOriginal and populate
  2. Create Second ListBox ListUserSelection, keep it empty initially
  3. Provide buttons as under:

    Button '>' means add currently selected item from ListFieldsOrginial to ListUserSelection at end; and remove that item from ListFieldsOriginal

    Button '<' means remove currenly selected item from lstUserSelection; and add that item back to ListFieldsOriginal (of course at end)

NOTE: If adding item back to ListFieldsOriginal is your requirement then extra coding is required to find its appropriate index in the ListFieldsOriginal.

Alternative UI Design - B

  1. Create One CheckedListBox ListFieldsOriginal and populate
  2. Create one ListBox ListUserSelection, keep it empty initially
  3. Define ItemCheck event handler for ListFieldsOriginal to add/remove items to/from ListUserSelected.

    if (e.CurrentValue==CheckState.Unchecked)
    {
       string item = ListFieldsOriginal.Items[item];
       ListUserSelection.Items.Add(item);
    }
    else
    {
       string item = ListFieldsOriginal.Items[item];
       ListUserSelection.Items.Remove(item);
    }
    

Upvotes: 0

Matthew Watson
Matthew Watson

Reputation: 109557

Here's an approach you can take.

  1. To make the affected comboboxes easy to distinguish, put them all in a GroupBox container.
  2. Write a validation method for your group box.
  3. Subscribe to the group box Validating event by attaching it to your validation method.
  4. In your validation method, loop through all the ComboBox controls in the group box and check if there are any duplicates, and issue an error if so.

For example, assuming the group box is called groupBox1:

private void GroupBox1_Validating(object sender, CancelEventArgs e)
{
    base.OnValidating(e);
    var selectedIndices = groupBox1.Controls.OfType<ComboBox>().Select(item => item.SelectedIndex);
    var anyDuplicates = selectedIndices.GroupBy(x => x).Any(x => x.Count() > 1);

    if (!anyDuplicates)
        return;

    MessageBox.Show("There are duplicates!");
    e.Cancel = true;
}

And subscribe to the group box Validating event in the Form1 constructor:

public Form1()
{
    InitializeComponent();
    groupBox1.Validating += GroupBox1_Validating;
}

Sometimes when validating like this, you need to prevent the validation logic from executing if the user clicks the Cancel button. You're supposed to be able to set the CausesValidation property of the Cancel button to false to prevent this, but I find that it doesn't work for me.

Instead, I just use a bool cancelling field which I set to true in the Cancel button handler:

private void cancelButton_Click(object sender, EventArgs e)
{
    cancelling = true;
    this.Close();
}

bool cancelling;

And then add the following to the start of GroupBox1_Validating():

if (cancelling)
    return;

Upvotes: 1

Nino
Nino

Reputation: 7095

You can do it like this (quick and dirty):

Add SelectedIndexChanged handler for all three comboboxes (in Form_Load in example)

comboBox1.SelectedIndexChanged += CheckComboBoxes;
comboBox2.SelectedIndexChanged += CheckComboBoxes;
comboBox3.SelectedIndexChanged += CheckComboBoxes;

in CheckComboBoxes method do your checking:

 private void CheckComboBoxes(object sender, EventArgs e)
 {
     if (comboBox1.SelectedIndex == comboBox2.SelectedIndex ||
         comboBox1.SelectedIndex == comboBox3.SelectedIndex ||
         comboBox2.SelectedIndex == comboBox3.SelectedIndex)
             MessageBox.Show("comboboxes are not unique");
 }

EDIT: this is approach when having n comboboxes. Put all items into list, select distinct values and compare that distinct count with items count... Something like this:

private void CheckComboBoxes(object sender, EventArgs e)
{
    List<string> comboValues = new List<string>();
    foreach (Control c in this.Controls)
    {
        if (c is ComboBox && !string.IsNullOrEmpty((c as ComboBox).SelectedItem.ToString()))
        comboValues.Add((c as ComboBox).SelectedItem.ToString());
    }
    if (comboValues.Distinct().ToList().Count < comboValues.Count)
        MessageBox.Show("not all combos are unique");
}

Upvotes: 1

Related Questions