对CollectionViewSource感到困惑(SelectedItem在组合框中不起作用)

本文关键字:组合 不起作用 SelectedItem CollectionViewSource | 更新日期: 2023-09-27 18:30:08

我有一堆组合,它们共享相同的可用选项。这些选择是在我的ViewModel公开的集合中提供的。一切都很好。

我现在想对这些选择进行排序,所以我决定从ViewModel中公开ICollectionView,而不是通常的ReadonlyObservableCollection<T>,并在ViewModel中对集合视图进行排序。

class EditStuffViewModel : ViewModelBase
{
    public EditStuffViewModel (ObservableCollection<Choice> choices)
    {
        Choices = new CollectionViewSource() { Source = choices }.View;
        Choices.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
    }
    public ICollectionView Choices
    {
        get;
        private set;
    }
    //snip other properties
}

这一切都很好,只是现在我的所有组合现在都同步了它们的选择

这不是我想要的。我希望选择是共享的,但选择是正常绑定的。我想我知道我的CollectionView正在跟踪选择,但我认为这是每个控件的行为选择。

我曾尝试在组合中显式设置IsSynchronizedWithCurrentItem="False",这成功地将它们解耦,但我的绑定SelectedItem从未在组合中被选中(ViewModel的绑定getter被调用,但结果从未被选中)。选择一个项目似乎确实正确地更新了ViewModel的setter。

我显然错过了CollectionView应该如何工作的一些基本内容。有人能启发我吗?

编辑:我的错,这个确实适用于IsSynchronizedWithCurrentItem="False"。有关详细信息,请参阅我的回答。

干杯。

对CollectionViewSource感到困惑(SelectedItem在组合框中不起作用)

很抱歉浪费了大家的时间,但设置IsSynchronizedWithCurrentItem="False"确实有效。我在排序的同时还添加了一个过滤器,默认选择的值不在筛选的项目列表中。哎呀。

至于为什么我需要明确地关闭IsSynchronizedWithCurrentItem,而我通常从不在标准集合上这样做,MSDN 上有一些线索

true如果SelectedItem始终与ItemCollection中的当前项同步false如果SelectedItem从未与当前项目同步仅当Selector使用CollectionView时,SelectedItem才与当前项同步,则为Nothing。默认值为Nothing

换句话说,如果显式使用CollectionView,而不是在普通集合上使用默认视图,则可以获得选择同步。

我已经有一段时间没有接触过WPF了,但我认为对于要维护的所选项目,每个组合框都需要不同的CollectionViewSource实例。

我认为这是因为SelectedItem属性被绑定到CollectionViewSource对象的选定项目状态属性(我猜View对象有它),并且ComboBoxes都共享同一个源实例,因此它们的选定项目现在是同步的。

因此,只需为每个组合框使用不同的CollectionViewSource实例即可。您仍然可以共享相同的源选项。您只需要不同的虚拟机,因为您的组合框应该彼此独立。


类似的东西(未经测试):

class EditStuffViewModel : ViewModelBase
{
    public EditStuffViewModel (ObservableCollection<Choice> choices)
    {
        ChoiceViews = new List<ICollectionView>();
        for (var i = 0; i < 10; i++) {
            var viewSource = new CollectionViewSource() { Source = choices };
            viewSource.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
            ChoiceViews.Add(viewSource.View);
        }
    }
    public IList<ICollectionView> ChoiceViews
    {
        get; private set;
    }
    //snip other properties
}

然后将ComboBoxes绑定改为绑定到ChoiceViews的元素。