收集更改后,组合框丢失选择

时间:2012-03-22 01:58:49

标签: wpf combobox observablecollection

我有一个绑定到obvserable collection(OC)的WPF组合框:

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

在其他地方,在设置为数据上下文的对象中:

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

组合覆盖其ToString,一切都是桃子:组合框的下拉列表显示组合OC中的所有组合项目。组合框的选择框显示第一个组合的值。

现在,数据上下文对象必须更改其组合OC中的值:

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

这会导致组合框的选择框显示一个空字符串。 (下拉列表已关闭。但是,当我将其下拉时,它会显示正确的新组合,因此 绑定到更新的集合)。

我试图捕获SourceUpdated和(在我的绝望中)TargetUpdated事件(在那里设置SelectedIndex),但我的事件处理程序没有被调用!

所以我的问题是:当它绑定的可观察集合发生变化时,如何让WPF ComboBox刷新其选择框的值?

更新

我完全忘了提及,我不知道它是否重要,但组合框是在UserControl中。 UserControl的XAML如下所示:

<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上有断点。

首次加载包含用户控件的表单时,CbCombinationSelectionChanged将触发一次。正如@asktomsk所说,它确实被称为第二次清除组合集合时。

未触发源更新和目标更新 - 未调用CbCombinationSourceUpdated和CbCombinationTargetUpdated。

由于组合框位于用户控件内,而组合集合位于视图模型中,并且由于视图模型无法访问组合框,我没有机会设置所选的索引组合除非事件触发

:(

1 个答案:

答案 0 :(得分:3)

问题出在您的this.Combinations.Clear();中 执行此操作时,会设置SelectedItem = nullSelectedIndex = -1

所以你应该再次设置选择。如果您有权访问ComboBox,那么在填写组合列表后,只需编写此cbCombination.SelectedIndex = 0; 当然,您也可以将SelectedItem / SelectedIndex绑定到代码后面的某些属性。

顺便说一句
填写集合后也不需要调用NotifyPropertyChanged(@"Combinations");,因为Combinations已经实现了INotifyPropertyChanged

<强>更新

要检测到 ObservableCollection 已更改,请在 UserControl 代码中订阅 CollectionChanged 事件。确保您在集合更改之前订阅了

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

另一个建议

当您不需要更智能的逻辑而不仅仅在组合框中选择零索引时,上述方法就有效。 但通常你需要一个更复杂的逻辑来选择一些项目。在这种情况下,您可以向模型中添加新属性:

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

并将此属性绑定到组合框:

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

在这种情况下,您可以在填充组合集合时选择任何项目,它将在组合框中自动选择:

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

if (Combinations.Count > 0)
    SelectedCombination = Combinations[0];