收集更改后,组合框丢失选择 [英] Combo-box loses selection after collection changes

查看:136
本文介绍了收集更改后,组合框丢失选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆