Automatic ListView Grouping

sandeepparekh9 1 Tallied Votes 1K Views Share

Lets say you have lots of data your listview. Now you want to Group This data According to a Perticular Subitems.

For Example:

Suppose i have some books data in my ListView.
this listview items contains Author name and Books Title.

And there are 2000 Books in list view.

Now i want to group the data in listview according to the Authors.

Now lets say there are 50 Unique Authors , meaning we will have to create 50 Groups in listview.

this seem hectic, and i dont know if there is any inbuilt function to automatically group this items, but i have created mine To automatically do the above.

Hope it becomes usefull to someone.


How To Use The Code:

Lets say the author's sub item's index is 1 and listview name is LstBooks

then call the function like:

GroupListView(LstBooks,1)

and its done..

Unhnd_Exception commented: Thanks for the new idea. +8
Public Sub GroupListView(ByVal lstV As ListView, ByVal SubItemIndex As Int16)
        Dim flag As Boolean = True
        For Each l As ListViewItem In lstV.Items

            Dim strmyGroupname As String = l.SubItems(SubItemIndex).Text

            For Each lvg As ListViewGroup In lstV.Groups

                If lvg.Name = strmyGroupname Then
                    l.Group = lvg
                    flag = False
                End If

            Next

            If flag = True Then
                Dim lstGrp As New ListViewGroup(strmyGroupname, strmyGroupname)
                lstV.Groups.Add(lstGrp)
                l.Group = lstGrp
            End If

            flag = True

        Next
    End Sub
Member Avatar for Unhnd_Exception
Unhnd_Exception

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
dragonfly67 0 Newbie Poster

Thank you very much for both Solutions. I was looking exactly for that.

dragonfly67 0 Newbie Poster

I figured out, that the second version works a little faster. Anyway thank you very much

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.