Advanced User Interface Controls and Components
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.
There are two ways to assign a group to a specific item:
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.
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