I have a listview in .net winforms, there is limitation where items with over 259 charaacters are truncated. Most of the item strings I am dealing with are usually well below 250, but I'd like to be able to handle these long ones when they occasionally crop up.
To overcome this I am detecting when there is a string over 250, splitting it into smallers substrings, and creating a listviewitem for each.
This works fine, until the listview needs sorting. How can I "pin" these items together so that the pinned group is sorted by the first item in said group?
I have tried implementing a custom Icomparer class, however, this results in the items being correctly pinned together, but they are not in the correct postion in the list overall.
Imports System.Globalization
Public Class LinkedListViewColumnSorter
Implements System.Collections.IComparer
''' <summary>
''' The column to sort
''' </summary>
Private ColumnToSort As Integer
''' <summary>
''' The order of sort
''' </summary>
Private OrderOfSort As SortOrder
''' <summary>
''' The object compare
''' </summary>
Private ObjectCompare As CaseInsensitiveComparer
''' <summary>
''' Initializes a new instance of the <see cref="LinkedListViewColumnSorter" /> class.
''' </summary>
Public Sub New()
' Initialize the column to '0'.
ColumnToSort = 0
' Initialize the sort order to 'none'.
OrderOfSort = SortOrder.None
' Initialize the CaseInsensitiveComparer object.
ObjectCompare = New CaseInsensitiveComparer()
End Sub
''' <summary>
''' Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
''' </summary>
''' <param name="x">The first object to compare.</param>
''' <param name="y">The second object to compare.</param>
''' <returns>
''' A signed integer that indicates the relative values of <paramref name="x" /> and <paramref name="y" />, as shown in the following table.Value Meaning Less than zero <paramref name="x" /> is less than <paramref name="y" />. Zero <paramref name="x" /> equals <paramref name="y" />. Greater than zero <paramref name="x" /> is greater than <paramref name="y" />.
''' </returns>
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
Dim compareResult As Integer
Dim listviewX As ListViewItem
Dim listviewY As ListViewItem
' Cast the objects to be compared to ListViewItem objects.
listviewX = CType(x, ListViewItem)
listviewY = CType(y, ListViewItem)
'// exit if there is no data for the given column
If (ColumnToSort > listviewX.SubItems.Count - 1) OrElse (ColumnToSort > listviewY.SubItems.Count - 1) Then
Return 0
End If
Dim XValue As String = listviewX.SubItems(ColumnToSort).Text
Dim YValue As String = listviewY.SubItems(ColumnToSort).Text
Dim DecX, DecY As Decimal
Dim XInfo As LinkedListViewRowInfo = TryCast(listviewX.Tag, LinkedListViewRowInfo)
Dim YInfo As LinkedListViewRowInfo = TryCast(listviewY.Tag, LinkedListViewRowInfo)
If XInfo IsNot Nothing AndAlso XInfo.MultiRow AndAlso YInfo IsNot Nothing AndAlso YInfo.MultiRow Then
Return ObjectCompare.Compare(XInfo?.Index, YInfo?.Index)
ElseIf XInfo IsNot Nothing AndAlso XInfo.MultiRow Then
Return XInfo?.Index.CompareTo(0)
ElseIf YInfo IsNot Nothing AndAlso YInfo.MultiRow Then
Return 1
End If
'// Handle numbers stored as strings (sort based on numberic value not starting digit)
Dim XisDecimal As Boolean = Decimal.TryParse(XValue, NumberStyles.Any, CultureInfo.CurrentCulture, DecX)
Dim YisDecimal As Boolean = Decimal.TryParse(YValue, NumberStyles.Any, CultureInfo.CurrentCulture, DecY)
' Compare the two items.
If XisDecimal AndAlso YisDecimal Then
compareResult = ObjectCompare.Compare(DecX, DecY)
Else
compareResult = ObjectCompare.Compare(listviewX.SubItems(ColumnToSort).Text, listviewY.SubItems(ColumnToSort).Text)
End If
' Calculate the correct return value based on the object
' comparison.
If (OrderOfSort = SortOrder.Ascending) Then
' Ascending sort is selected, return typical result of
' compare operation.
Return compareResult
ElseIf (OrderOfSort = SortOrder.Descending) Then
' Descending sort is selected, return negative result of
' compare operation.
Return (-compareResult)
Else
' Return '0' to indicate that they are equal.
Return 0
End If
End Function
''' <summary>
''' Gets or sets the sort column.
''' </summary>
''' <value>
''' The sort column.
''' </value>
Public Property SortColumn() As Integer
Set(ByVal Value As Integer)
ColumnToSort = Value
End Set
Get
Return ColumnToSort
End Get
End Property
''' <summary>
''' Gets or sets the order.
''' </summary>
''' <value>
''' The order.
''' </value>
Public Property Order() As SortOrder
Set(ByVal Value As SortOrder)
OrderOfSort = Value
End Set
Get
Return OrderOfSort
End Get
End Property
End Class