收集更改后,组合框丢失选择 [英] Combo-box loses selection after collection changes
问题描述
我有一个WPF组合框绑定到一个obvserable集合(OC):
I have a WPF combo box bound to an obvserable collection (OC):
<ComboBox Name="cbCombination" ItemsSource="{Binding Combinations}"
SelectedIndex="0" />
在其他地方,在设置为数据上下文的对象中:
Elsewhere, in the object set as data context:
public ObservableCollection<Combination> Combinations { get; set; }
组合覆盖其ToString,一切都是peachy:组合框的下拉菜单显示所有组合项在组合OC。组合框的选择框显示第一个组合的值。
Combination overrides its ToString and everything is peachy: The combo-box's drop-down displays all Combination items in the Combinations OC. The combo-box's selection box displays the value of the first Combination.
现在,数据上下文对象必须更改它的组合OC:
Now, the data-context object has to change the values in its Combinations OC:
var combinationsList = CombinationsManager.CombinationsFor(someParam);
this.Combinations.Clear();
foreach (var combination in combinationsList)
this.Combinations.Add(combination);
NotifyPropertyChanged(@"Combinations");
这会导致组合框的选择框显示一个空字符串。 (下拉菜单已关闭,但当我将其下拉时,会显示正确的新组合,因此已绑定到更新的集合)。
This causes the combo-box's selection box shows an empty string. (The drop-down is closed. However, when I make it drop down, it does show the correct new Combinations, so it is bound to the updated collection).
我试图捕获SourceUpdated和(在我的配置中)TargetUpdated事件(设置SelectedIndex在那里),但我的事件处理程序没有调用!
I tried to capture both SourceUpdated and (in my dispair) TargetUpdated events (thining of setting the SelectedIndex there), but my event handlers didn't get called!
所以我的问题是:当一个WPF ComboBox被绑定的observable集合改变时,如何刷新它的选择框的值?
更新:
我完全忘记了,我不知道是否重要,但组合框在UserControl内。 UserControl的XAML如下所示:
I've totally forgotten to mention, and I don't know whether it's important, but the combo-box is within a UserControl. The UserControl's XAML looks like this:
<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>
在UserControl代码我有CbCombinationSelectionChanged,CbCombinationSourceUpdated和CbCombinationTargetUpdated的断点。
In the UserControl's code I have breakpoints on CbCombinationSelectionChanged, CbCombinationSourceUpdated and CbCombinationTargetUpdated.
当首次加载包含用户控件的表单时,CbCombinationSelectionChanged触发一次。
The CbCombinationSelectionChanged fires once when the form containing the user control is first loaded. It is indeed called a second time when the Combinations collection is cleared, as @asktomsk said.
源更新和目标更新不会被触发 - CbCombinationSourceUpdated和CbCombinationTargetUpdated不会被调用。
The source updated and target updated are not triggered - CbCombinationSourceUpdated and CbCombinationTargetUpdated are not called.
由于组合框位于用户控件内,并且组合集合在视图模型中,并且由于视图模型无法访问组合框,因此
As the combo box is inside a usercontrol and the Combinations collection is within the view model, and as the view model doesn't have access to the combo box, I have no opportunity to set the selected index of the combo unless the events fire.
:(
推荐答案
问题出现在 this.Combinations.Clear();
it,它设置 SelectedItem = null
和 SelectedIndex = -1
所以你应该重新设置选择。如果你有权访问你的ComboBox,然后在填充组合列表后写入 cbCombination.SelectedIndex = 0;
。
当然你也可以将SelectedItem / SelectedIndex绑定到代码中的某些属性。
So you should set selection again. If you have an access to your ComboBox then just write this cbCombination.SelectedIndex = 0;
after filling Combinations list.
Of course you can bind SelectedItem/SelectedIndex to some property in code behind too.
BTW
也不需要调用
已经实现
INotifyPropertyChanged
填充集合后,code> NotifyPropertyChanged(@Combinations code>。
BTW
Also it is not required to call NotifyPropertyChanged(@"Combinations");
after filling the collection because Combinations
already implements INotifyPropertyChanged
.
更新
> ObservableCollection 已更改,请在您的 UserControl 代码中订阅 CollectionChanged
To detect that your ObservableCollection was changed, subscribe to CollectionChanged event in your UserControl code behind. Make sure that you subscribed before collection changed!
Combinations.CollectionChanged += (s, e) =>
{
if (cbCombination.Items.Count > 0)
cbCombination.SelectedIndex = 0;
};
另一个建议
当你不需要一个更聪明的逻辑,而不仅仅是在组合框中选择零索引时,上述方法是有效的。
但是通常你需要一个更复杂的逻辑来选择一些项目。在这种情况下,您可以向模型中添加新属性:
Approach above is works when you do not need a smarter logic than just select zero index in combobox. But often you will need a more complex logic to select some item. In this case you may add new property to your model:
public Combination SelectedCombination
{
get{ return _selectedCombination; }
set
{
_selectedCombination = value;
NotifyPropertyChanged("SelectedCombination");
}
}
并将此属性绑定到您的组合框:
and bind this property to your combobox:
<ComboBox Name="cbCombination" ItemsSource="{Binding Combinations}"
SelectedIndex="0" SelectedItem={Bindings SelectedCombination} />
在这种情况下,您可以在填充Combinations集合时选择任何项目,并且将在组合框中自动选择:
In this case you can select any item when filling the Combinations collection and it will be automatically selected in combobox:
var combinationsList = CombinationsManager.CombinationsFor(someParam);
this.Combinations.Clear();
foreach (var combination in combinationsList)
this.Combinations.Add(combination);
if (Combinations.Count > 0)
SelectedCombination = Combinations[0];
这篇关于收集更改后,组合框丢失选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!