【问题标题】:ICollectionView Does not support changes to its sourcecollectionICollectionView 不支持更改其 sourcecollection
【发布时间】:2017-03-09 16:43:46
【问题描述】:

我正在开发一个 WPF 应用程序,我最近在 ICollectionView 中封装了几个 ObservableCollections,以便我可以实现排序和过滤。

Private _EntriesSource As New BankEntry.Collection
Public ReadOnly Property Entries As ICollectionView = Windows.Data.CollectionViewSource.GetDefaultView(_EntriesSource)

排序和过滤工作得很好,但是由于这样做它似乎不太友好,尽管将任何接触集合的东西包装在 Dispatcher 线程调用中或使用 BindingOperations.EnableCollectionSynchronization 我仍然收到错误说这个集合不支持对其源集合的更改...

我正在尝试做的事情的示例只是 MyCollection.Add(item) 或 MyCollection.Remove(item)。

从 ObservableCollections 移动到 ICollectionView 是否走错了方向? 是否有更好的方法对 ObservableCollections 进行排序和过滤,同时保持从集合中添加和删除项目的能力?

【问题讨论】:

  • 为什么得到视图却丢失视图源?

标签: .net wpf


【解决方案1】:

在大多数情况下,对数据进行排序和分组是视图(不是 CollectionView 而是 MVVM 视图)的功能,因此最好的方法是在 XAML 中创建 CollectionViewSource 并将其绑定到您的可观察集合,然后绑定您的控件到 CollectionViewSource

<StackPanel>
    <StackPanel.Resources>
        <CollectionViewSource x:Key="cvsBodies" Source="{Binding Bodies}" Filter="CollectionViewSource_Filter">
            <CollectionViewSource.SortDescriptions>
                <ComponentModel:SortDescription Direction="Ascending" PropertyName="Name"/>
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </StackPanel.Resources>
    <ItemsControl ItemsSource="{Binding Mode=OneWay, Source={StaticResource cvsBodies}}"/>
</StackPanel>

您还可以在 VM 上创建 CollectionViewSource

public class VM
{
    public VM()
    {
        CollectionView.Source = Items;
        CollectionView.Filter += CollectionView_Filter;
        //only required if you are initialising the collection with values
        CollectionView.View.Refresh();

    }

    private void CollectionView_Filter(object sender, FilterEventArgs e)
    {
         //filter logic
    }

    public CollectionViewSource CollectionView { get; } = new CollectionViewSource();
    public ObservableCollection<int> Items { get; } = new ObservableCollection<int>(Enumerable.Range(1,1000) );
}

【讨论】:

  • 为了完整性,如果其他人在看,我认为 ComponentModel: 将需要以下声明 xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
  • Mike 这太棒了 - 你能扩展过滤吗? EventTrigger 和 Binding Path=Filter 的目的是什么? Filter 属性会是什么样子?我认为 CollectionViewSource_Filter 将是布尔函数背后的简单代码。
  • CollectionViewSource 过滤器的方式是通过过滤器事件,如果过滤器是纯基于视图的,那么只需使用 EventHandler 即可,但是如果您使用 ViewModel 进行过滤,则需要绑定将事件过滤到过滤器命令这是 EventTrigger 正在做的事情,过滤器的工作方式非常简单,列表中的每个项目都被逐个馈送到过滤器事件中,并且 Accepted 事件 arg 设置为 true 或 false 参见@987654321 @
  • 如果不清楚,请使用 Filter= 或 EventTrigger 绑定,不要同时使用
  • 在我的过滤器绑定中发现一个错误,默认 InvokeCommandAction 不支持传递事件参数,因此从示例中删除
猜你喜欢
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多