views:

502

answers:

2

Hi guys,
I have a List<ListViewItem> and I've used it in a ListView in VirtualMode
There are 5000 items in the list and I'm gonna sort it with LINQ and OrderBy whenever a Column of the ListView is clicked , so I have written below code :


List<ListViewItem> ListOfItems = new List<ListViewItem>();
ListViewColumnSorter lvwColumnSorter;

void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
{
    try
    {
        // Determine if clicked column is already the column that is being sorted.
        if (e.Column == lvwColumnSorter.SortColumn)
        {
            // Reverse the current sort direction for this column.
            if (lvwColumnSorter.Order == SortOrder.Ascending)
            {
                lvwColumnSorter.Order = SortOrder.Descending;
            }
            else
            {
                lvwColumnSorter.Order = SortOrder.Ascending;
            }
        }
        else
        {
            // Set the column number that is to be sorted; default to ascending.
            lvwColumnSorter.SortColumn = e.Column;
            lvwColumnSorter.Order = SortOrder.Ascending;
        }

        if (lvwColumnSorter.Order == SortOrder.Descending)
            this.ListOfItems.OrderByDescending(a => a, new CompareListItemsClass(e.Column, lvwColumnSorter.Order));
        else
            this.ListOfItems.OrderBy(a => a, new CompareListItemsClass(e.Column, lvwColumnSorter.Order));

        this.listView1.VirtualListSize = ListOfItems.Count;
        this.listView1.Refresh();
    }
    catch { }
}

public class CompareListItemsClass : IComparer<ListViewItem>
{
    private CaseInsensitiveComparer ObjectCompare = new CaseInsensitiveComparer();
    private SortOrder OrderOfSort;
    private int ColumnToSort;

    public CompareListItemsClass(int columnIndex, SortOrder sortOrder)
    {
        ColumnToSort = columnIndex;
        OrderOfSort = sortOrder;
    }

    public int Compare(ListViewItem listviewX, ListViewItem listviewY)
    {
        // Compare the two items
        try
        {
            compareResult = ObjectCompare.Compare(
                int.Parse(listviewX.SubItems[ColumnToSort].Text),
                int.Parse(listviewY.SubItems[ColumnToSort].Text));
        }
        catch
        {
            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text,
                listviewY.SubItems[ColumnToSort].Text);
        }


        // Calculate correct return value based on object comparison
        if (OrderOfSort == SortOrder.Ascending)
        {
            // Ascending sort is selected, return normal result of compare operation
            return compareResult;
        }
        else if (OrderOfSort == SortOrder.Descending)
        {
            // Descending sort is selected, return negative result of compare operation
            return (-compareResult);
        }
        else
        {
            // Return '0' to indicate they are equal
            return 0;
        }
    }

    int IComparer<ListViewItem>.Compare(ListViewItem x, ListViewItem y)
    {
        throw new NotImplementedException();
    }
}

but nothing happen ! I expect at least an exception was throw !
Could you please guide me ?
Thanks.

+3  A: 

The OrderBy and OrderByDescending extension methods do not modify the collection, they return an sequence of items of the collection in the specified order. In your code, you just discard the result of those methods, so nothing happens...

If you need to sort the collection "in place" (i.e. modify the actual order of the items), use the List<T>.Sort method.


EDIT

To implement descending AND ascending order, it's actually easier to do it with a Comparison<T> than with an IComparer<T>, since you just need to negate the result... Here's an example :

Comparison<ListViewItem> temp = (x, y) =>
{
    int xvalue = int.Parse(x.SubItems[e.Column].Text);
    int yvalue = int.Parse(y.SubItems[e.Column].Text);
    return xvalue.CompareTo(yvalue);
};

Comparison<ListViewItem> comparison;
if (lvwColumnSorter.Order == SortOrder.Ascending)
{
    comparison = temp;
}
else
{
    comparison = (x, y) => -temp(x, y);
}

this.ListOfItems.Sort(comparison);
Thomas Levesque
Could you please post a sample code for Descending and Ascending sorting with List<T>.Sort ?
Mohammad
Thanks Thomas Levesque
Mohammad
+1  A: 

LINQ methods doesn't affect the collection, they return a new collection. You can use the ToList method to turn the result into a list and assign it back to the list variable:

this.ListOfItems = this.ListOfItems.OrderBy(a => a, new CompareListItemsClass(e.Column, lvwColumnSorter.Order)).ToList();
Guffa