C# 从CollectionChanged事件处理程序中的ObservableCollection中删除项

C# 从CollectionChanged事件处理程序中的ObservableCollection中删除项,c#,observablecollection,C#,Observablecollection,我希望能够拒绝一些项目后,他们已经被添加到一个可观的收集。我无法将ObservableCollection子类化或使用任何类型的视图,因此我似乎仅限于使用定义的一个事件处理程序(CollectionChanged)对禁止项执行.Remove()。如果在提出事件和随后处理事件之间的短时间内存在这些项目,则可以;这些项不应该保留在集合中。似乎不允许在CollectionChanged事件处理程序中调用.Remove()。运行时.NET抛出InvalidOperationException: “无法在

我希望能够拒绝一些项目后,他们已经被添加到一个可观的收集。我无法将ObservableCollection子类化或使用任何类型的视图,因此我似乎仅限于使用定义的一个事件处理程序(CollectionChanged)对禁止项执行.Remove()。如果在提出事件和随后处理事件之间的短时间内存在这些项目,则可以;这些项不应该保留在集合中。似乎不允许在CollectionChanged事件处理程序中调用.Remove()。运行时.NET抛出InvalidOperationException:

“无法在CollectionChanged事件期间更改ObservableCollection。”

我个人认为.NET应该允许我这样做。如果我创造了一个无限循环,那是我自己的错

我想使用的代码如下所示:

myCollection.CollectionChanged += (sender, args) =>
{
    if (args.Action == NotifyCollectionChangedAction.Remove)
        return;
    foreach (var itm in myCollection)
    {
        if (itm.name == "Fred")
            myCollection.Remove(itm);
    }
}
我不确定我有什么选择。使用调度器似乎不起作用。触发另一个事件并将.Remove调用放入另一个处理程序是我想到的唯一其他选项。

签出


话虽如此,如果您仍然想走这条路,您可以旋转一个,如果您真的想修改一个集合,那么您将要遍历该集合的一个副本。这是因为您试图修改foreach循环中的集合,这会让您感到悲伤

范例

var copy = new ObservableCollection<YourType>(collection)
foreach(var item in copy)
{
    if(item.Name == "Fred")
    {
        collection.Remove(item);
    }

}
var copy=新的可观察集合(集合)
foreach(副本中的var项目)
{
如果(item.Name==“Fred”)
{
收集。移除(项目);
}
}
也就是说,我同意Anurag的观点,即您不应该在CollectionChanged事件中使用observablecollection来执行此类操作。

使用
ToList()
来迭代列表

foreach(var item in collection.ToList())
{
    if(item.Name == "Fred")
    {
        collection.Remove(item);
    }
}

在oncollectionchanged中使用了此选项,并且可以正常工作(WPF和MVVM示例):


我尝试使用设置标志来请求集合添加/删除更改,然后当System.Windows.Interop.ComponentDispatcher.ThreadIdle调用我的处理程序时,执行添加或删除操作。这很有效。但是,在集合中使用try finally将处理程序更改为取消连接,然后重新连接该集合更改的事件处理程序也绕过了重新进入问题:

private void MyDataGrid_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
{
    try
    {
        dgRows.CollectionChanged -= MyDataGrid_CollectionChanged;
        
        switch( e.Action )
        {
            case NotifyCollectionChangedAction.Add:
                if( SomeTestIsTrue() )
                dgRows.Add( new vmRowObject() );
                break;
        }
    }
    finally
    {
        dgRows.CollectionChanged += MyDataGrid_CollectionChanged;
    }
}

无法从ObservableCollection中删除项。这就是其中的全部要点。。。您只能从正在包装的集合中删除项。不应在集合已更改的事件处理程序中执行此操作。在允许更改集合之前,请先执行筛选器。如果这不是一个合适的改变,不要让收藏被改变。我知道这是旧的,可能不是正确的方法;但这就是我所做的,可能会帮助别人。当我试图从OberservableCollection中删除所选文件时,我也遇到了同样的问题,即获取该异常。当my Messenger处理第二个文件删除请求时,CollectionChange事件仍在触发。所以在我的CollectionChanged事件处理程序中,我必须添加
lock(this.Files){//code of the event}
一旦我这样做了,我再次运行我的程序,选择多个文件并点击delete。这次也不例外,因为删除必须等待。嗨,链接似乎不再可用。
private void MyDataGrid_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
{
    try
    {
        dgRows.CollectionChanged -= MyDataGrid_CollectionChanged;
        
        switch( e.Action )
        {
            case NotifyCollectionChangedAction.Add:
                if( SomeTestIsTrue() )
                dgRows.Add( new vmRowObject() );
                break;
        }
    }
    finally
    {
        dgRows.CollectionChanged += MyDataGrid_CollectionChanged;
    }
}