LIDOR SYSTEMS

Advanced User Interface Controls and Components

Add Expandable Groups in ListView .NET

Created: 20 September 2013

IntegralUI ListView can arrange items in different groups, and by default each group can expand or collapse its content. There are many ways to expand a specific group, either using a mouse clicks or specific keys from a keyboard. In this article we will explain how to do that.

Expand/Collapse Groups in ListView .NET
Download Sample - ListView with Expandable Groups

Different Ways to Expand/Collapse Groups

There are two ways to assign a group to a specific item:

  1. By adding the item to the specific group Items collection
  2. By setting the Group property of the item to point to a specific group

In following example we are using the group index to arrange items in specific groups. If we have a limited number of groups we are using a modifier depending on the number of present groups:

// Assign items to groups depending on their index

int groupIndex = 0;

for (int i = 0; i < this.listView1.Items.Count; i++)

{

groupIndex = i % (int)numGroups.Value;

this.listView1.Groups[groupIndex].Items.Add(this.listView1.Items[i]);

}

' Assign items to groups depending on their index

Dim groupIndex As Integer = 0

For i As Integer = 0 To Me.listView1.Items.Count - 1

groupIndex = i Mod CInt(numGroups.Value)

Me.listView1.Groups(groupIndex).Items.Add(Me.listView1.Items(i))

Next

Each group contains an expand button shown in group header aligned to the right side. Whenever the expand button is clicked, the group will expand or collapse, depending on its current state. However, in some cases this is not convenient and we may need to expand/collapse groups when group header is clicked not just the expand button. We can solve this by handling the Click event of the ListView and locate the group which header is clicked. Then we can expand or collapse the group:

private void listView1_Click(object sender, EventArgs e)

{

// Convert the mouse cursor positions to local value

Point mousePos = this.listView1.ContentPanel.PointToClient(Control.MousePosition);

 

// Get the group which header is clicked using the mouse position

LidorSystems.IntegralUI.Lists.ListViewGroup group = this.listView1.GetGroupAt(mousePos.X, mousePos.Y);

if (group != null)

{

Rectangle groupTextRect = group.Bounds;

 

// Subtract the width of expand button to avoid callbacks from clicks on expand button

groupTextRect.Width -= 20;

 

// Make sure group also gets expanded or collapsed when a click is made over group header

if (groupTextRect.Contains(mousePos))

{

if (group.IsExpanded)

group.Collapse();

else

group.Expand();

}

}

}

Private Sub listView1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles listView1.Click

' Convert the mouse cursor positions to local value

Dim mousePos As Point = Me.listView1.ContentPanel.PointToClient(Control.MousePosition)

 

' Get the group which header is clicked using the mouse position

Dim group As LidorSystems.IntegralUI.Lists.ListViewGroup = Me.listView1.GetGroupAt(mousePos.X, mousePos.Y)

If group IsNot Nothing Then

Dim groupTextRect As Rectangle = group.Bounds

 

' Subtract the width of expand button to avoid callbacks from clicks on expand button

groupTextRect.Width -= 20

 

' Make sure group also gets expanded or collapsed when a click is made over group title

If groupTextRect.Contains(mousePos) Then

If group.IsExpanded Then

group.Collapse()

Else

group.Expand()

End If

End If

End If

End Sub

Additonally a group can be expanded or collapsed also by using the ENTER or SPACE keys, whenever a group has the input focus.

Make Group Always Expanded

By default each group is expanded and can also become collapsed either using mouse clicks or keyboard. We can also make some groups always expanded by simple handling the BeforeGroupCollapse event where we can determine wheter a group is about to collapse and cancel the process.

private void listView1_BeforeGroupCollapse(object sender, LidorSystems.IntegralUI.ObjectCancelEventArgs e)

{

if (e.Object is LidorSystems.IntegralUI.Lists.ListViewGroup)

{

LidorSystems.IntegralUI.Lists.ListViewGroup group = (LidorSystems.IntegralUI.Lists.ListViewGroup)e.Object;

 

// If group is marked as always expanded, cancel the collapse of it

if (group.Tag != null && group.Tag.ToString() == "ALWAYS_EXPANDED")

e.Cancel = true;

}

}

Private Sub listView1_BeforeGroupCollapse(ByVal sender As Object, ByVal e As LidorSystems.IntegralUI.ObjectCancelEventArgs) Handles listView1.BeforeGroupCollapse

If TypeOf e.[Object] Is LidorSystems.IntegralUI.Lists.ListViewGroup Then

Dim group As LidorSystems.IntegralUI.Lists.ListViewGroup = DirectCast(e.[Object], LidorSystems.IntegralUI.Lists.ListViewGroup)

 

' If group is marked as always expanded, cancel the collapse of it

If group.Tag IsNot Nothing AndAlso group.Tag.ToString() = "ALWAYS_EXPANDED" Then

e.Cancel = True

End If

End If

End Sub

There is no way in telling which group shoukld remain always expanded. We can solve this by adding a value to the Tag property, for example “ALWAYS_EXPANDED” string value, which we will use to mark the group. In event bode, we can add the code which checkes whether the group Tag value is matching this and if it is, cancel the collapse process.

A sample project in C# and VB showing how to create expandable groups in ListView and how to make some groups always expanded is available for download from here: ListView with Expandable Groups

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.