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 differentBindingList<T>
.combo1.DataSource = yourList.ToList();
combo2.DataSource = yourList.ToList();You can use different
BindingSource
for them and set your list asDataSource
of BindingSourcecombo1.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 ComboBox
to 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
Why Is Infinity Printed as "8" in the Windows 10 Console
How to Unit Test with Ilogger in ASP.NET Core
Retrieve the Respective Coordinates of All Words on the Page with Itextsharp
How to Move Rigidbody Gameobject
Bind Multiple Combobox to a Single List - Issue: When I Select an Item, All Combo Boxes Change
Using Profiles in Automapper to Map the Same Types with Different Logic
Random Errors Using Wait for Element Clickable Method in Selenium
ASP.NET MVC: Calling a Method from a View
Issue with List.Add() Only Saving the Last Added Item
How to Store (And Manage) Application License Information
How to Set Attributes Values Using Reflection
How to Return the Current Action in an ASP.NET MVC View
Efficiently Get Full JSON String in JSONconverter.Readjson()
From Excel to Datatable in C# with Open Xml
Run Selenium Tests in Multiple Browsers One After Another from C# Nunit