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 appear at given index '0'"
but I'm setting the NotifyCollectionChangedAction enum to Remove as the code below.
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));
}
}
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)
);
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With