Combo-box loses choice after collection changes

I have a WPF combo box associated with an obvserable collection (OC):

<ComboBox Name="cbCombination" ItemsSource="{Binding Combinations}" SelectedIndex="0" /> 

Elsewhere, in an object defined as a data context:

  public ObservableCollection<Combination> Combinations { get; set; } 

The combination overrides ToString, and all peach: in the drop-down list with the list all Combined elements in Combination OC are displayed. The combo box selection box displays the value of the first combination.

The data context object should now change the values ​​in its OC combinations:

  var combinationsList = CombinationsManager.CombinationsFor(someParam); this.Combinations.Clear(); foreach (var combination in combinationsList) this.Combinations.Add(combination); NotifyPropertyChanged(@"Combinations"); 

This causes the combo box to display an empty string. (The popup window is closed. However, when I pop it out, it shows the correct new combinations, so it is tied to the updated collection).

I tried to capture both SourceUpdated and (in my case) TargetUpdated events (exception to the installation of SelectedIndex there), but my event handlers were not called!

So my question is: How to make WPF ComboBox update the value of its selection window when the observed collection is associated with changes?

Update :

I completely forgot to mention, and I don’t know if this is important, but the combo-box is in UserControl. UserControl XAML is as follows:

 <UserControl x:Class="...CombinationsToolBar" .... mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <ToolBarTray Name="toolBarTray1" > <ToolBar Name="toolBar1"> <ComboBox Name="cbCombination" ItemsSource="{Binding Path=Combinations, NotifyOnSourceUpdated=True, IsAsync=True}" SelectedIndex="0" IsEditable="False" SelectionChanged="CbCombinationSelectionChanged" SourceUpdated="CbCombinationSourceUpdated" TargetUpdated="CbCombinationTargetUpdated"></ComboBox> </ToolBar> </ToolBarTray> 

In UserControl code , I have breakpoints on CbCombinationSelectionChanged, CbCombinationSourceUpdated and CbCombinationTargetUpdated.

CbCombinationSelectionChanged is run once when the form containing the user control is loaded first. This is really called the second time the collection of combinations is cleared, as @asktomsk said.

The original updated and updated target does not start - CbCombinationSourceUpdated and CbCombinationTargetUpdated are not called.

Since the combo box is inside user control, and the collection of combinations is in the view model, and since the view model does not have access to the corresponding field, I have no way to set the selected combo index if events are not lit.

: (

+1
wpf combobox observablecollection
source share
1 answer

The problem is in your this.Combinations.Clear();
When you do this, it sets SelectedItem = null and SelectedIndex = -1

So you must set the choice again. If you have access to your ComboBox, just write this cbCombination.SelectedIndex = 0; after filling out the list of combinations.
Of course, you can associate SelectedItem / SelectedIndex with some property in the code.

BTW
It is also not required to call NotifyPropertyChanged(@"Combinations"); after filling out the collection, because Combinations already implements INotifyPropertyChanged .

Update

To find that your ObservableCollection has been changed, subscribe to the CollectionChanged event in your UserControl code. Make sure you sign up before the collection changes!

 Combinations.CollectionChanged += (s, e) => { if (cbCombination.Items.Count > 0) cbCombination.SelectedIndex = 0; }; 

Another suggestion

The approach above works when you don’t need more reasonable logic than just choosing a null index in combobox. But often you will need more complex logic to select some element. In this case, you can add a new property to your model:

 public Combination SelectedCombination { get{ return _selectedCombination; } set { _selectedCombination = value; NotifyPropertyChanged("SelectedCombination"); } } 

and bind this property to your summary declaration:

 <ComboBox Name="cbCombination" ItemsSource="{Binding Combinations}" SelectedIndex="0" SelectedItem={Bindings SelectedCombination} /> 

In this case, you can select any element when filling out the collection of combinations, and it will be automatically selected in the combo box:

 var combinationsList = CombinationsManager.CombinationsFor(someParam); this.Combinations.Clear(); foreach (var combination in combinationsList) this.Combinations.Add(combination); if (Combinations.Count > 0) SelectedCombination = Combinations[0]; 
+3
source share

All Articles