Bind Multiple Combobox to a Single List - Issue: When I Select an Item, All Combo Boxes Change

Bind multiple ComboBox to a single List - Issue: When I select an item, all combo boxes change

Since you are binding all combo boxes to the same data source - a single list - they are using a single BindingManagerBase.

So when you choose an item from one of combo boxes, the current Position of the shared binding manager base changes and all combo boxes goes to that position of their shared data source.

To solve the problem you can bind them to different data source:

  • You can bind them to yourList.ToList() or any other list for example different BindingList<T>.

    combo1.DataSource = yourList.ToList();
    combo2.DataSource = yourList.ToList();
  • You can use different BindingSource for them and set your list as DataSource of BindingSource

    combo1.DataSource = new BindingSource { DataSource= yourList};
    combo2.DataSource = new BindingSource { DataSource= yourList};

Also as another option:

  • You can use different BindingContext for your combo boxes. This way even when you bind them to a single list, they are not sync anymore.

    combo1.BindingContext = new BindingContext();
    combo1.DataSource = yourList;
    combo2.BindingContext = new BindingContext();
    combo2.DataSource = yourList;

In fact all controls of the form use a shared BindingContext. When you bind 2 controls to a same data source, then they also use the same BindingManagerBase this way, when you for example move to next record, all controls move to next record an show value from bound property of next record. This is the same behavior that you are seeing from your combo boxes. Being sync for controls which are using the same BindingManagerBase is a desired behavior. Anyway sometimes we don't need such behavior. The post shares the reason and the solution.

Binding multiple ComboBoxes to the same ItemsSource causes problems

I'm guessing you have IsSynchronizedWithCurrentItem="True" on both ComboBox controls. Remove it from both, and that should solve your problem.

Setting IsSynchronizedWithCurrentItem="True" tells the ComboBox that it should keep its SelectedItem in sync with the CurrentItem in the underlying ICollectionView. Since you are binding directly to a collection, and not a collection view, both combo boxes are using the default collection view, which is a common instance shared across controls. When one of your combo boxes updates the collection view's selection, the other sees the change and updates its own selection to match it.

Binding List to several ComboBoxes

Use a BindingList<T>
This class allows you to handle the interaction with your list separately for each of the combos

For example

List<string> names = new List<string>()
{"Steve", "Mark", "Luke", "John", "Robert"};

BindingList<string> bl1 = new BindingList<string>(names);
ComboBox_Rank_0.DataSource = bl1;

BindingList<string> bl2 = new BindingList<string>(names);
ComboBox_Rank_1.DataSource = bl2;

The BindingList<T> requires using System.ComponentModel; and notice that you don't require the new string[] syntax in the constructor of your list

Multiple Combobox with same Itemsource but the SelectedItem should be different - WPF

You could define different SelectedItem for each ComboBox, and then create a wrapper of the SharedItemSource for each ComboBoxto filter out the SelectedItem of other ComboBox. eg:

C# :

    public IEnumerable<string> ComboboxItems1
{
get
{
return ComboboxItems.Where(x => x != SelectedItem2 && x != SelectedItem3);
}
}

public string SelectedItem1
{
get { return _selectedItem1; }
set
{
if (_selectedItem1 != value)
{
_selectedItem1 = value;
RaisePropertyChanged("SelectedItem1");
RaisePropertyChanged("ComboboxItems2"); //raise propertychanged to refresh GUI
RaisePropertyChanged("ComboboxItems3");
}
}
}

public IEnumerable<string> ComboboxItems2
{
get
{
return ComboboxItems.Where(x => x!=SelectedItem1&&x!=SelectedItem3);
}
}

public string SelectedItem2
{
get { return _selectedItem2; }
set
{
if (_selectedItem2 != value)
{
_selectedItem2 = value;
RaisePropertyChanged("SelectedItem2");
RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
RaisePropertyChanged("ComboboxItems3");
}
}
}

public IEnumerable<string> ComboboxItems3
{
get
{
return ComboboxItems.Where(x => x != SelectedItem1 && x != SelectedItem2);
}
}

public string SelectedItem3
{
get { return _selectedItem3; }
set
{
if (_selectedItem3 != value)
{
_selectedItem3 = value;
RaisePropertyChanged("SelectedItem3");
RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
RaisePropertyChanged("ComboboxItems2");
}
}
}

XAML:

<ComboBox SelectedItem="{Binding SelectedItem1}" ItemsSource="{Binding ComboboxItems1}" />
<ComboBox SelectedItem="{Binding SelectedItem2}" ItemsSource="{Binding ComboboxItems2}" />
<ComboBox SelectedItem="{Binding SelectedItem3}" ItemsSource="{Binding ComboboxItems3}" />

Multiple ComboBox with single DataSource

Give each ComboBox their own BindingSource:

comboBox1.DataSource = new BindingSource(source, string.Empty);
comboBox2.DataSource = new BindingSource(source, string.Empty);

Multiple Combo Boxes with shared Binding - Display error after first selection from box

You're sharing ComboBoxItems among different ComboBoxes. Those are visual elements and you're trying to share them among different parents. I'm not surprised it breaks.

You need each ComboBox to have a distinct collection of ComboBoxItem instances. You can most simply do that by exposing your items as ObservableCollection<String> and letting each ComboBox create its own ComboBoxItems. Bind the collection the same way you're binding the collection you've got; I think that declaring and populating that collection should almost be the only change you need to make, unless you need to disable port items for all boxes at once, rather than just the one they were selected in. Your SelectedItem on the combobox will be the string, though, rather than `ComboBoxItem, so the guts of those loops will have to change a bit.

When you disable a ComboBoxItem, it will be disabled only for the ComboBox it belongs to, naturally. If you want COM4 disabled for all boxes, you'll have to do that in a loop.

Or you could go a little more MVVM: If this were me, I would create the series of ComboBoxes in a templated ItemsControl bound to a collection of some class that had a SelectedPort property, and I would use a custom class for the items as well, just a simple thing with String PortName and bool IsPortEnabled. I'd bind IsPortEnabled to ComboBoxItem.IsEnabled in the XAML. There'd be a lot less code, but it's a big jump conceptually from where you're at now. We can go there if you're interested.

Synchronizing two comboboxes bound to the same collection and to the same selected item

You're recreating your collection every time you reference it, so SelectedItem is referencing a different object. In effect, your two combo boxes are using different collections as ItemsSources. Change the code to

public ObservableCollection<CustomerDto> CustomerCodeDtos
{
get
{
if(_customerCodes==null)
{
_customerCodes = _databaseService.GetAllCustomers();
}
return _customerCodes;
}
}


Related Topics



Leave a reply



Submit