Trying to sort a ListView with unchecked items at the top and then by ID: compare routine throws an odd exception
I'm building a desktop to-do list app, and in my UI I have a ListView
control which lists all the items in each list. Each item/row has a checkbox which updates the status of that item in the database when it is checked or unchecked. So far so good!
What I am attempting to do is re-sort the list whenever a checkbox is clicked, so that the list is always sorted with the unchecked items at the top, and then by ID (which is an int
value stored in the Tag
property of each ListViewItem
when the list is loaded).
I've written a custom comparer implementing IComparer
and call Sort()
on the ListView
in the ItemChecked
event handler:
/// <summary>
/// Complete or uncomplete a todo item when it's checked/unchecked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
Here is my comparer:
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;
}
}
However, when I check an item, the following exception is thrown when t开发者_如何转开发he sort is attempted:
System.ArgumentOutOfRangeException was unhandled
Message="InvalidArgument=Value of '-1' is not valid for 'index'.\r\nParameter name: index"
Source="System.Windows.Forms"
ParamName="index"
And in the debugger, if I inspect the item1.Checked
property in the compare routine I see:
'item1.Checked' threw an exception of type 'System.ArgumentOutOfRangeException'
The other item's Checked
property shows up fine. What am I doing wrong here?
It looks like the Index of your ListViewItem
is -1
(the Checked property uses Index
internally). That's normally the case only before the ListViewItem
is added to the ListView
.
In your case, the item might have been temporarily removed from the list during sorting. In other words, it does not look safe to access the Checked
property from a sort routine.
Try to return 0
instead if -1
because it seems that the value returned by Compare()
becomes an index of the item.
精彩评论