是啥导致 BindingList<T> 中的 ListChangedType.ItemMoved ListChange 事件?
Posted
技术标签:
【中文标题】是啥导致 BindingList<T> 中的 ListChangedType.ItemMoved ListChange 事件?【英文标题】:What causes a ListChangedType.ItemMoved ListChange Event in a BindingList<T>?是什么导致 BindingList<T> 中的 ListChangedType.ItemMoved ListChange 事件? 【发布时间】:2010-11-17 05:50:21 【问题描述】:我有一个 BindingList(T),我在 DataGrid 中显示它。我正在观察 ListChanged 事件并在触发 ListChanged 事件时执行不同的操作。
我正在检查事件的 ListChangeType 参数以检查列表是如何更改的,然后做出相应的响应。但是,我注意到有一个 ListChanged 事件类型 ItemMoved。
我有“上移”和“下移”按钮来在列表中上下移动项目。但这些实际上是删除选定的项目,然后将其重新插入到更高或更低的位置。
但是,我没有看到 BindingList(T) 的任何方法看起来会移动列表中的项目。那么我是否遗漏了什么,或者只是没有办法在 BindingList 中移动一个也会引发 ItemMoved 类型 ListChanged 事件的项目?
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 事件,通过删除/添加执行移动,使用适当的 ItemMoved ListChangedType 自己引发 ListChanged 事件,然后恢复引发 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;
*完全未经测试的代码,但它应该说明要点。
【讨论】:
要点看起来是正确的,只是想我应该指出将项目移动到较低的索引不适用于此代码 - this.Remove(item) 将移动索引。至少你一次性插入你的项目,最坏的情况是你尝试插入到列表的末尾。【参考方案2】:如果绑定源应用了排序,则触发,如果您更改排序字段中保存的数据,然后更改记录的位置,然后触发事件。
【讨论】:
【参考方案3】:与 Scott 的回答类似,您可以执行以下扩展方法:
//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())。可能会有所帮助...
【讨论】:
以上是关于是啥导致 BindingList<T> 中的 ListChangedType.ItemMoved ListChange 事件?的主要内容,如果未能解决你的问题,请参考以下文章
BindingList<T>.Sort() 表现得像 List<T>.Sort()
List<T> vs BindingList<T> 优点/缺点
NullReferenceException未处理C#(使用BindingList)[重复]