INotifyCollectionChanged:添加项目不会出现在给定索引'0'

时间:2011-05-04 13:04:41

标签: c# wpf

我正在制作一个可观察的课程。 Add方法工作正常。但后来我试图调用Remove()方法我得到了这个错误:

  

“添加的项目不会出现在给定的索引'0'”

但是我将NotifyCollectionChangedAction枚举设置为Remove,如下面的代码所示。

    public class ObservableOrderResponseQueue : INotifyCollectionChanged, IEnumerable<OrderResponse>
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    private List<OrderResponse> _list = new List<OrderResponse>();


    public void Add(OrderResponse orderResponse)
    {
        this._list.Add(orderResponse);
        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, orderResponse, 0));
        }
    }

    public void RemoveAt(int index)
    {
        OrderResponse order = this._list[index];
        this._list.RemoveAt(index);
        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, order, index));
        }
    }

    public void Remove(OrderResponse orderResponse)
    {
        var item = _list.Where(o => o.OrderDetail.TrayCode == orderResponse.OrderDetail.TrayCode).FirstOrDefault();
        int index = _list.IndexOf(item);

        this._list.RemoveAt(index);
        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
        }
    }

4 个答案:

答案 0 :(得分:8)

您确定错误是使用Remove方法吗?错误消息和源代码表明它在Add方法中。尝试在_list.Count - 1的构造函数中使用正确的索引NotifyCollectionChangedEventArgs

CollectionChanged(this, new NotifyCollectionChangedEventArgs(
                                              NotifyCollectionChangedAction.Add, 
                                              orderResponse, _list.Count - 1)
                 );

答案 1 :(得分:2)

如果我猜,我会说这句话......

var item = _list.Where(
    o => o.OrderDetail.TrayCode == orderResponse.OrderDetail.TrayCode)
    .FirstOrDefault();

...因为它调用FirstOrDefault(),可能会返回null。设置一个断点,看看实际发生了什么。

为此,为什么要进行查询呢?由于您要传递要删除的对象,为什么不简单地执行此操作:

int index = _list.IndexOf(item);
if (index >= 0)
    this._list.RemoveAt(index);
//then pass item to your eventargs since it was the object removed.

更好,因为List<T>有自己的Remove(T object)方法:

this._list.Remove(item);
//this may throw an exception or not if the item is not in that collection,
// which is behavior you should probably retain

图片的标题说明

如何举起CollectionChanged事件可能存在竞争条件。在检查null和提升它之间,订阅者可以从事件中删除其委托。这是避免这种情况的简单方法:

// initialize it with an empty lamda so it is never null
public event NotifyCollectionChangedEventHandler CollectionChanged = (o,e) => {};

现在你可以提高它,永远不需要检查它是否为空:

public void Add(OrderResponse orderResponse)
{
    this._list.Add(orderResponse);
    CollectionChanged(this,
        new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,
            orderResponse, this._list.Count - 1));
}

这不会使它完全是线程安全的,但它确保引发事件不会引发空引用异常。

答案 2 :(得分:0)

我通过Reflector找出了问题所在,并弄清楚了导致此异常的原因可能是Equals对于列表中实际上相等的对象未返回true;或operator ==

答案 3 :(得分:0)

当我尝试使用 Remove 参数创建新的 NotifyCollectionChangedEventArgs 时收到此异常正在被移除。

有一次,我将传入 NotifyCollectionChangedEventArgs 的项目更改为我要从内部列表中删除异常的实际项目

<块引用>

“添加的项目没有出现在给定的索引..”

走了。