This was a good idea to add to my extended listview.
I went ahead and added the GroupBy sub to the listview control itself instead of having it as a stand alone sub.
I made a couple of mods to your original sub and added an overloaded GroupBy that will group the Items by property name. I use the ListViewItem's tag to hold the group name so if the user interface can change from grouped to un-grouped the tag can be used to group the items again without reloading.
I'm using the tag property as an example but you could technically group the items by ForeColor, Tag, Checked, or any other property.
Using the ListViewPlus
'This will group the items by ForeColor but you can pass in any property name you want.
ListViewPlus1.GroupBy("ForeColor")
The ListViewPlus Cass. Just add a class and copy and paste the code, Hit build, and drag it and drop it onto the form.
Public Class ListViewPlus : Inherits ListView
Public Sub GroupBy(ByVal subItemIndex As Integer, Optional ByVal defaultGroupName As String = "Default")
Me.Groups.Clear()
Dim GroupName As String
'Add a default group of our own with the default group name passed in.
Me.Groups.Add(defaultGroupName, defaultGroupName)
For Each ListViewItem As ListViewItem In Me.Items
'If the listview items subitem count is bad or it has no text
'in that subitem then set its group as the default group and
'continue.
If ListViewItem.SubItems.Count <= subItemIndex OrElse String.IsNullOrEmpty(ListViewItem.SubItems(subItemIndex).Text) Then
ListViewItem.Group = Me.Groups(defaultGroupName)
Continue For
End If
'Get the listviewItem's subitem's text and change it to all
'lower case with the first letter uppercase. This will
'eliminate text with different casings being made seperate
'groups.
GroupName = ListViewItem.SubItems(subItemIndex).Text
GroupName = CStr(GroupName(0)).ToUpper & GroupName.Substring(1).ToLower
'Add the group if it hasn't and finally set the listviewItem's Group.
If Me.Groups(GroupName) Is Nothing Then
Me.Groups.Add(GroupName, GroupName)
End If
ListViewItem.Group = Me.Groups(GroupName)
Next
End Sub
Public Sub GroupBy(ByVal propertyName As String, Optional ByRef defaultGroupName As String = "Default")
Me.Groups.Clear()
Dim GroupName As String
Dim PropertyInfo As Reflection.PropertyInfo
Dim PropertyValue As Object
Me.Groups.Add(defaultGroupName, defaultGroupName)
For Each ListViewItem As ListViewItem In Me.Items
GroupName = defaultGroupName
'Get the property with the specified name
PropertyInfo = ListViewItem.GetType.GetProperty(propertyName, Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)
'If the property was a real property and its value is not nothing
'then add its ToString value as the group name.
If PropertyInfo IsNot Nothing Then
PropertyValue = PropertyInfo.GetValue(ListViewItem, Nothing)
If PropertyValue IsNot Nothing Then
GroupName = PropertyValue.ToString
End If
End If
'Check for group existence
If Me.Groups(GroupName) Is Nothing Then
Me.Groups.Add(GroupName, GroupName)
End If
'Set the Listview Items group.
'If the property name passed in ended up with a
'invalid value then the group name will be the
'default group name.
ListViewItem.Group = Me.Groups(GroupName)
Next
End Sub
End Class