INotifyCollectionChanged: Added item does not appear at given index '0'

前端 未结 3 1228
情歌与酒
情歌与酒 2020-12-20 18:03

I\'m making a observable class. The Add methods works fine. But then I\'m trying to call the Remove() method I get this error:

\"Added item does not a

相关标签:
3条回答
  • 2020-12-20 18:22

    I tracked down the issue with Reflector and figured out the cause of this exception might refer to Equals not returning true for actually equal objects in your list; or maybe operator ==.

    0 讨论(0)
  • 2020-12-20 18:26

    Are you sure the error is with the Remove method? The error message and your source code indicate it is in the Add method. Try using the correct index _list.Count - 1 in the constructor of NotifyCollectionChangedEventArgs:

    CollectionChanged(this, new NotifyCollectionChangedEventArgs(
                                                  NotifyCollectionChangedAction.Add, 
                                                  orderResponse, _list.Count - 1)
                     );
    
    0 讨论(0)
  • 2020-12-20 18:27

    If I were to guess, I'd say that this line...

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

    ...because it calls FirstOrDefault(), may be returning null. Set a breakpoint and see what's actually going on.

    To that end, why even do that query? Since you're passing in the object to be removed, why not simply do this:

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

    Even better, since List<T> has its own Remove(T object) method:

    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
    

    Sidenotes

    There is also a possible race condition in how you raise the CollectionChanged event. In between checking for null and raising it a subscriber could remove its delegate from the event. Here's an easy way to avoid that:

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

    Now you can just raise it and never need to check if it is null:

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

    This doesn't make it completely thread-safe, but it's an easy way of making sure raising the event won't throw a null reference exception.

    0 讨论(0)
提交回复
热议问题