尝试使用顶部未选中的项目对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()
返回的值似乎成为项的索引。