0

I'm scratching my head a bit with this.

I'm using winforms to build a business application and I'm using a lot of ListViews. I've got one particular list which, when populated with items can set the forecolor property of the item to either red or black depending on the type of item it is. I wanted to sort this so that all red items appeared at the top of the list using a custom implementation of IComparer. It works, but it works in reverse, as in all red items appear at the bottom. Here is my code.

    '//Populate list
    For Each i In allStock.Where(Function(c) c.StockStatusID <> 6)
        '//Add item, color in red if it is not contained within a certain date range
    Next

    '//Use my custom built IComparable implementing class(SortListByRedText) to sort items so that red items appear at the top.
    Dim sorter As New SortListByRedText()
    StockManagementList.ListViewItemSorter = sorter
    StockManagementList.Sort()

'//Custom IComparer
Public Class SortListByRedText
    Implements IComparer


Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare

    Dim item1 = CType(x, ListViewItem)
    Dim item2 = CType(y, ListViewItem)

    If item1.ForeColor = Color.Red And item2.ForeColor = Color.Red Then
        Return 0
    ElseIf item1.ForeColor = Color.Red And item2.ForeColor = Color.Black Then
        Return 1
    ElseIf item1.ForeColor = Color.Black And item2.ForeColor = Color.Red Then
        Return -1
    Else
        Return 0
    End If

End Function

End Class

EDIT: I have reversed the -1 and 1 order in my comparer as a fix, but I don't like putting in a fix when I don't understand why it works. Surely anything returning -1 should be sent to the bottom of the list not the top?

BenM
  • 4,218
  • 2
  • 31
  • 58

1 Answers1

1

Here is how you go. Reverse the -1 and 1 part.

Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare

    Dim item1 = CType(x, ListViewItem)
    Dim item2 = CType(y, ListViewItem)

    If item1.ForeColor = Color.Red And item2.ForeColor = Color.Red Then
        Return 0
    ElseIf item1.ForeColor = Color.Red And item2.ForeColor = Color.Black Then
        Return -1
    ElseIf item1.ForeColor = Color.Black And item2.ForeColor = Color.Red Then
        Return 1
    Else
        Return 0
    End If    
End Function

Also note you're ignoring any other colors other than Black or Red. You may need to consider that.

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • I had already done this as it was the obvious thing to do in this situation. What I don't get is why does the sort method put all of the objects which return -1 to the top of the list and not the bottom? – BenM Oct 28 '13 at 09:50
  • Because that is how `IComparer` works. When you return `-1` that means `x` is lesser than `y`. so the smaller element(x here) will be moved to top rather than bottom. Is that clear? – Sriram Sakthivel Oct 28 '13 at 10:43
  • Yep that makes sense, in one sense I get why, smaller number default to the top of the list, but on the other hand it seems a bit counter intuative because an item returned as greater than I would expect it to appear in a position greater than those which are less than. Accepted your answer, thanks for the discussion. – BenM Oct 28 '13 at 10:56