Что вызывает событие ListChangedType.ItemMoved ListChange в BindingList <T>?
У меня есть BindingList (T), который я показываю в DataGrid. Я наблюдаю за событиями ListChanged и выполняю различные действия при возникновении события ListChanged.
Я проверяю аргумент ListChangeType, чтобы проверить, как был изменен список, и затем соответствующим образом реагировать. Однако я заметил, что существует тип события ListChanged ItemMoved.
У меня есть кнопки для "Move Up" и "Move Down" для перемещения элементов вверх и вниз по списку. Но они фактически удаляют выбранный элемент, а затем снова вставляют его в более высокое или нижнее положение.
Однако я не вижу никакого метода BindingList (T), который выглядит так, будто он перемещает элемент в списке. Так что я что-то упустил или нет способа переместить элемент в BindingList, который также вызовет событие ListChanged типа ItemMoved?
void FloorCollection_ListChanged(object sender, ListChangedEventArgs e)
{
if (e.ListChangedType == ListChangedType.ItemAdded)
{
//DO STUFF
}
else if (e.ListChangedType == ListChangedType.ItemDeleted)
{
//DO STUFF
}
else if (e.ListChangedType == ListChangedType.ItemMoved)
{
//HOW DO I GET THIS CODE TO RUN?
}
else if (e.ListChangedType == ListChangedType.ItemChanged)
{
//DO STUFF
}
}
Ответы
Ответ 1
К сожалению, ничто в BindingList не вызовет событие ListChanged с ListChangedType, установленным в ListChangedType.ItemMoved. BindingList наследует от Collection, который не предоставляет никакой поддержки для "перемещения" элементов в списке. BindingList не добавляет никакой поддержки этому типу поведения.
Если вам действительно нужно/нужно отвечать на события ListChangedType.ItemMoved, лучшим вариантом является извлечение собственного класса из BindingList и предоставление собственных методов Move. Внутри этих методов вам необходимо временно приостановить сбор событий ListChanged, выполнить перемещение, удалив/добавив, поднимите событие ListChanged самостоятельно с помощью соответствующего ItemMoved ListChangedType, а затем верните приостановление создания событий ListChanged.
Это выглядело бы так: */
public class CustomBindingList<T> : BindingList<T>
{
public void Move(T item, int index)
{
bool raiseListChangedEvents = this.RaiseListChangedEvents;
try
{
this.RaiseListChangedEvents = false;
int oldIndex = this.IndexOf(item);
this.Remove(item);
this.InsertItem(index, item);
this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, index, oldIndex));
}
finally
{
this.RaiseListChangedEvents = raiseListChangedEvents;
}
}
}
* Полностью непроверенный код, но он должен проиллюстрировать основные моменты.
Ответ 2
Он запускает, если для источника привязки применяется сортировка, если вы изменили и данные, которые хранятся в поле сортировки, а затем измените положение записи, а затем триггеры события.
Ответ 3
В отличие от ответов Скотта, вы можете сделать что-то вроде этого метода расширения:
//Dumping ground for miscellaneous functions
public static class Misc
{
//Swap items at index positions 'index0' and 'index1' in the list
public static void Swap<T>(this BindingList<T> list, int index0, int index1, bool reset_bindings)
{
if (index0 == index1) return;
bool raise_events = list.RaiseListChangedEvents;
try
{
list.RaiseListChangedEvents = false;
T tmp = list[index0];
list[index0] = list[index1];
list[index1] = tmp;
list.RaiseListChangedEvents = raise_events;
if (reset_bindings) list.ResetBindings();
}
finally
{
list.RaiseListChangedEvents = raise_events;
}
}
}
Это не приводит к событиям ItemMoved, которые вы выполняли, но сохраняет необходимость подкласса BindingList < > . Вы можете поднять событие Reset (используя ResetBindings()) после того, как закончите перемещение элементов в списке. Может быть полезно...