Chris Graves
Chris Graves

Reputation: 121

ListView.Sort() not working correctly with IComparer C#

Within my code, I have a ListView called allocations which stores the location name and the picking priority as its columns. At the moment, it looks something like this:-

|    Location    |    Picking Priority    |
|----------------|------------------------|
|   Location A   |          1000          |
|   Location B   |          750           |
|   Location C   |          1000          |

I am attempting to use an IComparer to sort by the picking priority so that the location with the lowest picking priority is at the top of the list and the rest follow in ascending order. Currently, this is the code I have:-

public ArrayList getSortedListView()
{
    ListView lvLocations = new ListView();
    lvLocations.ListViewItemSorter = new ListViewItemComparer();

    // Reads CSV file to get required location. 
    // lvGlobalLocations is filled with every location on the system.

    foreach (ListViewItem item in lvGlobalLocations.Items)
    {
        if (item.Text == <location name>)
        {
            lvLocations.Items.Add((ListViewItem)item.Clone());
            lvLocations.Sort();
        }
    }

    // Cycles through ListView and stores location names in ArrayList to be returned.
}


class ListViewItemComparer : IComparer
{
    public int Compare(object a, object b)
    {
        ListViewItem lvi1 = (ListViewItem)a;
        ListViewItem lvi2 = (ListViewItem)b;
        int int1 = int.Parse(lvi1.SubItems[1].Text);
        int int2 = int.Parse(lvi2.SubItems[1].Text);
        if (int1 > int2)
            return -1;
        else if (int1 < int2)
            return 1;
        else
            return 0;
    }
}

How can I get it to compare correctly so that the ArrayList returned is in the correct order?

Upvotes: 0

Views: 1364

Answers (2)

Alex Zhukovskiy
Alex Zhukovskiy

Reputation: 10035

As said above you should never use ArrayList. Today is 24 feb 2016, stop kicking .Net 1.1 corps, please.

You can achieve this with LINQ:

public IEnumerable<ListViewItem> getSortedListView()
{
    ListView lvLocations = new ListView();
    lvLocations.ListViewItemSorter = new ListViewItemComparer();

    // Reads CSV file to get required location. 
    // lvGlobalLocations is filled with every location on the system.

    return lvGlobalLocations.Items.Where(item => item.Text == <location name>).OrderBy(x => x.Whatever);
}

or use List.Sort (yes, generic list has a lot of useful methods):

public List<ListViewItem> getSortedListView()
{
    ListView lvLocations = new ListView();
    lvLocations.ListViewItemSorter = new ListViewItemComparer();

    // Reads CSV file to get required location. 
    // lvGlobalLocations is filled with every location on the system.

    var list = new List<ListViewItem>(lvGlobalLocations.Items.Where(item => item.Text == <location name>))
    list.Sort((a, b) => a.Whatever.CompareTo(b.Whatever));
    return list;
}

Upvotes: 1

N_tro_P
N_tro_P

Reputation: 693

You do not need that much actually. Lamda's allow for property specification in the sort. Just make sure you are defining your "sub item" or understand the signature of the object.

var sorted = list.OrderByDescending(item => item.PropertyToSortBy);

If the requirement is to use the comparitor object you must actually use it.

var sorted = list.Sort(comparitor);

It will use the default sort defined by the object itself. This indicates yet another sort possibility. Have the contained object be ICompariable.

Again, I would simply use a lamda expression. This is a trivial sort. Once you have to sort on numerous properties and other processing logic you would consider either a comparitor or putting the sort logic on the object itself.

Upvotes: 1

Related Questions