尝试使用顶部未选中的项目对ListView进行排序,然后按ID:compare例程抛出一个奇怪的exception

我正在构建一个桌面待办事项列表应用程序,在我的UI中,我有一个ListView控件,列出了每个列表中的所有项目。 每个项目/行都有一个复选框,用于在选中或取消选中时更新数据库中该项目的状态。 到现在为止还挺好!

我试图做的是每当单击一个复选框时重新排序列表,以便列表总是按顶部未选中的项目排序,然后按ID(这是存储在每个的Tag属性中的int值)排序加载列表时的ListViewItem )。

我编写了一个实现IComparer的自定义比较器,并在ItemChecked事件处理程序的ListView上调用Sort()

 ///  /// Complete or uncomplete a todo item when it's checked/unchecked ///  ///  ///  private void _taskList_ItemChecked(object sender, ItemCheckedEventArgs e) { var list = sender as ListView; var itemId = e.Item.Tag.ToString(); if(e.Item.Tag != null) { if(e.Item.Checked) // Do some database stuff here to mark as complete else // Do some database stuff here to mark as not completed } // Resort the listview list.ListViewItemSorter = new TaskListComparer(); list.Sort(); } 

这是我的比较器:

 public class TaskListComparer : IComparer { public TaskListComparer() { } public int Compare(object a, object b) { // Convert the two passed values to ListViewItems var item1 = a as ListViewItem; var item2 = b as ListViewItem; // Get the unique ID's of the list items (stored in the Tag property) var item1Id = Convert.ToInt32(item1.Tag); var item2Id = Convert.ToInt32(item2.Tag); // First sort on the Checked property (unchecked items should be at the top) if (item1.Checked && !item2.Checked) return 1; else if (!item1.Checked && item2.Checked) return -1; // If both items were checked or both items were unchecked, // sort by the ID (in descending order) if (item1Id > item2Id) return 1; else if (item1Id < item2Id) return -1; else return 0; } } 

但是,当我检查项目时,尝试排序时会抛出以下exception:

 System.ArgumentOutOfRangeException was unhandled Message="InvalidArgument=Value of '-1' is not valid for 'index'.\r\nParameter name: index" Source="System.Windows.Forms" ParamName="index" 

在调试器中,如果我在比较例程中检查item1.Checked属性,我会看到:

 'item1.Checked' threw an exception of type 'System.ArgumentOutOfRangeException' 

另一个项目的Checked属性显示正常。 我在这做错了什么?

看起来ListViewItem的索引是-1 ( Checked属性在内部使用Index )。 通常只有在ListViewItem添加到ListView之前才会出现这种情况。

在您的情况下,在排序期间可能已暂时从列表中删除该项目。 换句话说,从排序例程访问Checked属性看起来并不安全。

如果为-1 ,则尝试返回0因为看起来Compare()返回的值似乎成为项的索引。