Событие ListChanged для IBindingList запускает тип ListChangedType.ItemDeleted, когда элементы удаляются, возможно, пользователем, удаляющим строку в элементе управления datagrid, привязанном к списку. Проблема в том, что NewIndex в списке недействителен в этом событии, он был удален, а элемент, который был удален, недоступен. Должно быть событие ItemDeleting, но я сомневаюсь, что они когда-нибудь это исправят.





На самом деле он не предназначен для этой цели. NewIndex - это индекс, в котором элемент находился при удалении, и для связанных элементов управления полезно иметь возможность находить связанный с ними элемент отображения в своих собственных списках и удалять его.
Какой вариант использования вы хотите включить с ItemDeleting?
Да, это довольно неприятно, но есть простой обходной путь. Я создаю класс BindingListBase<T>, который использую для всех своих списков вместо обычного BindingList<T>. Поскольку мой класс наследуется от BindingList<T>, у меня есть доступ ко всем его защищенным членам, включая метод RemovedItem.
Это позволяет мне забрать, когда предмет удален. Вы могли бы делать то же, что и я, и иметь список mRemovedItems, в который я всегда добавляю элементы, или создавать собственное событие ItemRemoved.
См. Мой пример кода ниже:
Public MustInherit Class BindingListBase(Of T)
Inherits BindingList(Of T)
Protected mRemovedItems As New List(Of T)
Protected Overrides Sub ClearItems()
MyBase.ClearItems()
mRemovedItems.Clear()
End Sub
Protected Overrides Sub RemoveItem(ByVal index As Integer)
Dim item As T = MyBase.Item(index)
MyBase.RemoveItem(index)
mRemovedItems.Add(item)
End Sub
Public ReadOnly Property RemovedItems as List(Of T)
Get
Return mRemovedItems
End Get
End Property
End Class
Я сделал что-то похожее на то, что сделал Адам Валпид, то есть реализовал свой собственный класс с обработчиком событий ListChanging. Это позволяет мне работать с элементом, который будет удален из списка, до того, как он действительно удалится.
В ответ на вопрос Sunlight относительно варианта использования ... среди прочего, я использую его для удаления обработчиков событий, которые были помещены в содержащийся элемент, когда он был помещен в список. Мои элементы данных содержат уровень серьезности ошибки, определенный во время проверки, и элементы графического интерфейса, которые они привязаны, чтобы отображать эту серьезность ошибки в виде цвета фона. Когда уровень серьезности ошибки элемента данных изменяется, элемент графического интерфейса пользователя должен быть обновлен. Поэтому я должен поместить обработчик событий HighestSeverityChanged в элемент данных, когда он отображается (сам по себе или как часть отображаемого списка), и мне нужно удалить этот обработчик событий, когда элемент графического интерфейса не привязан к элемент данных.
Вот моя версия класса BindingList, который реализует событие ItemRemoved, а не хранит вторичный список удаленных элементов.
public class ItemRemovedEventArgs : EventArgs
{
public Object Item { get; set; }
public ItemRemovedEventArgs(Object item)
{
this.Item = item;
}
}
public delegate void ItemRmoveEventHandler(Object sender, ItemRemovedEventArgs e);
public class BindingListRedux<T> : BindingList<T>
{
public BindingListRedux() : base() { }
public BindingListRedux(IList<T> list) : base(list) { }
public event ItemRmoveEventHandler ItemRemoved;
protected void OnItemRemoved(ItemRemovedEventArgs e)
{
if (ItemRemoved != null)
{
ItemRemoved(this, e);
}
}
protected override void RemoveItem(int index)
{
Object item = base[index];
base.RemoveItem(index);
this.OnItemRemoved(new ItemRemovedEventArgs(item));
}
}