Click here to Skip to main content
Email Password   helpLost your password?

Sample Image - GroupableListView.png

Introduction

Some time ago, I thought about writing a small extension to the ListView control. This would dynamically create a graphic user interface to allow the end-user create/modify groups, something like �GROUP BY� in SQL. The control will automatically create a ToolStrip and a ToolStripButton for each column.

Usage

To use the control, just add ExListView.cs to your project, and switch the GroupsGUIs property to true, if you want to give the possibility to group items for the users.

Properties

Example

I prepared a small example project, with a ListView which contains some employees. Each employee has a name, sex, and a job. So, if the user wants to group the employees by sex, he just needs to press one button, and the ListView will analyze each ListViewItem and create groups for the data. It creates one group for each different data in selected colums.

Here you see an example of ListView, grouped by Sex and Job:

Sample Image - GroupableListView.png

Code

To analyze and create the groups, I wrote a GroupBy(ColumnHeader[] Headers) method, it�s a simple thread-safe method with a few loops which add groups for each new different data found.

delegate void dGroupBy(ColumnHeader[] Headers);
public void GroupBy(ColumnHeader[] Headers)
{
    if (this.InvokeRequired)
    {
        dGroupBy d = new dGroupBy(GroupBy);
        this.Invoke(d, new object[] { Headers });
    }
    else
    {
        //code

        foreach (ListViewItem lvi in this.Items)
        {
            string header = "";

            foreach (ColumnHeader ch in Headers)
            {
                header += " " + 
                   lvi.SubItems[ch.Index].Text;
            }
            ListViewGroup group = 
                new ListViewGroup(header);
            ListViewGroup found = null;
            foreach (ListViewGroup g in Groups)
            {
                if (g.Header == group.Header)
                { found = g; break; }
            }
            if (found == null)
            {
                this.Groups.Add(group);
                group.Items.Add(lvi);
            }
            else
            {
                found.Items.Add(lvi);
            }
        }
    }
}

Sample Image - GroupableListView.png

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralVery nice extension!
Sam Jacobs
13:40 17 Mar '10  
Works great! Have a quick question ...
I'm trying to add a line or 2 of explanatory text above the tabstrip.
Although I can see it at design time, when I run the app, the text disappears (even though I modified the co-ordinates of the control). Any ideas what I might be missing? Thanks!
Generalwrite text in Grouping
Rohit Mahajan
22:39 21 May '08  
Hello

Is it possible to write text in Grouping like

TESTING
---------------------------------

Whats going on?

to

TESTING
--------------------
whats
going
on?

where it is one Text only?
GeneralVista Style Group/Sort
Alexandru Stanciu
18:54 27 Feb '08  
Any idea on how to get something like the Windows Vista Explorer ListView with the nice per column Sort/Group feature?
QuestionNo scroll bar
Bill W
5:29 15 Nov '07  
I really like your group by list view. It saved me the hassle of having to figure this out and write it myself Smile !

One thing I'm seeing though is that when I have a large number of items in the list with the groups, the scroll bars do not appear, even though the setting on the control is to show scrollbars.

Any idea why the scroll bar will not show up?

Thanks.

Bill
QuestionStrange Issue
-_-_-_-_-_
22:10 22 Aug '07  
HI.

I like this control a lot, but i have a issue with it, and for the life of me, i can't figure out what the problem is.
i load up a XML file in my program. (around 15 records).
I then add the items to the list:

foreach (base_Item bi in Items)
{
dlg.pb_Progress.PerformStep();

ListViewItem lvi = new ListViewItem(bi.Type, bi.IconNum);
lvi.SubItems.Add(bi.Name_Short);
lvi.SubItems.Add(bi.Description_Short);
lvi.SubItems.Add(bi.Genre);
lvi.SubItems.Add(bi.NumberOfDisks.ToString());
lvi.SubItems.Add(bi.Format);
lvi.SubItems.Add(bi.Reference);
elv.Items.Add(lvi);
}

this is a valid way of adding to a list. but when i do it, there is nothing shown in the list. it is all clear. Yet, when i just create a temporary ListView (just a standard one), and give it this identical code, (of course change the name), it all shows up fine. I have had it working 100%, and then it just stops working. i even set up some temporary ExListViews, and it does the same thing. really strange. i would love to use this control, but at this stage it's not suitableFrown .
Any suggestions ?
Thanks
AnswerRe: Strange Issue
-_-_-_-_-_
22:18 22 Aug '07  
I also as an experiment, renamed the ExListView to lv_test, and a standard ListView to elv. and didn't change any code, and the same results, the ListView has nice data, and the ExListView has nothing - so that means that the code works fine. Strange..
QuestionWidth-Problem when ListView in LargeIcon-Mode
Stephan Mantel
4:21 17 Jun '07  
Hello,

First of all let me say that I really like your control. It's exactly what I was looking for.

But I have a strange problem when I use the ListView in LargeIcon-Mode (myView.View = LargeIcon) and use the grouping feature. When there is no grouping, the items are displayed correctly. But when I group them, the items are displayed with a very large gap between them. E.g. when without grouping 5 items are displayed in one row, with grouping only 2 items are displayed, because of a large gap between them. I tried to change the column width property, but that had no effect.

Does anyone has a clue, how I can solve this? Every hint is welcome. Wink

Thanx in advance.
Stephan
GeneralGrouping Sorted
chancer101
5:56 16 May '07  
Let me start by saying I love this control, just made an enhancement which I thought I'd share with you all.....

When clicking on one of the "grouping" buttons, the order seems to be from the first item in each group, not by the group name. Smile

Modify the GroupBy method to include the following calls to the ListViewGroupSorter

public void GroupBy(ColumnHeader[] Headers)
{
if (this.InvokeRequired)
{
dGroupBy d = new dGroupBy(GroupBy);
try
{
this.Invoke(d, new object[] { Headers });
}
catch (Exception ex)
{

//throw;
return;
}

}
else
{
//code
foreach (ListViewItem lvi in this.Items)
{
string header = "";

foreach (ColumnHeader ch in Headers)
{
header += lvi.SubItems[ch.Index].Text + " / ";
}

ListViewGroup group = new ListViewGroup(header);
ListViewGroup found = null;

foreach (ListViewGroup g in Groups)
{
if (g.Header == group.Header)
{ found = g; break; }
}
if (found == null)
{
this.Groups.Add(group);
group.Items.Add(lvi);

}
else
{
found.Items.Add(lvi);
}
}

// Copy the groups for the column to an array.
ListViewGroup[] groupsArray = new ListViewGroup[Groups.Count];
Groups.CopyTo(groupsArray, 0);

// Sort the groups and add them to myListView.
Array.Sort(groupsArray, new ListViewGroupSorter(SortOrder.Ascending));
this.Groups.Clear();
this.Groups.AddRange(groupsArray);
}
}



and added this class (from MSDN) to the control

// Sorts ListViewGroup objects by header value.
public class ListViewGroupSorter : IComparer
{
private SortOrder order;

// Stores the sort order.
public ListViewGroupSorter(SortOrder theOrder)
{
order = theOrder;
}

// Compares the groups by header value, using the saved sort
// order to return the correct value.
public int Compare(object x, object y)
{
int result = String.Compare(
((ListViewGroup)x).Header,
((ListViewGroup)y).Header
);
if (order == SortOrder.Ascending)
{
return result;
}
else
{
return -result;
}
}
}
GeneralSeem a bug
dvptUml
17:05 3 Apr '07  
Sorry, i'm not a programmer, just a financial manager !! and i never wrote an article (not enough time to learn programming...).
But i think i've found that bug : when you set a group and then unset it (and nor category is set), the border line still appear.
May I suggest to add in the void tsb_Click(object sender, EventArgs e) method after HeaderGroup.Remove... the following:
if (HeaderGroup.Count == 0)
{
this.Group.Clear();
return; // nothing to ask 'GroupBy'
}
I hope i'm not wrong since nobody told this ....

Not a programmer but DvptUml is my credo
Generaluse combobox instead of a toolstrip... [modified]
TheCardinal
22:04 17 Oct '06  
i it possible to use or support combobox instead of using a toolstrip.

it would be nice to use a combobox for the selection of columns to group instead of using a toolstrip Smile

anyway just a request.

Excellent control and keep up the good work Smile


-- modified at 14:39 Thursday 19th October, 2006
QuestionExpand/Collapse Group
riz332
23:06 3 Oct '06  
Can we add a button that will allow us to expand/collapse a group like in tree view?
AnswerRe: Expand/Collapse Group
sonofdaedalus
9:23 24 Jan '07  
I would also like this feature. Anyone have ideas how I would go about adding that feature to this control?

Thanks,
Andy.
QuestionRe: Expand/Collapse Group
Soxiz
12:32 11 Jun '07  
Did you ever find a way to do this? I would really love to see this as well so hope you found a way.

Mads
QuestionA Question
phonefans
8:41 15 Sep '06  
first,Thank you for you share this good idea!
I look you code,and i have a question:

public ExListView()
{
InitializeComponent();
this.tsGroups.SizeChanged += new EventHandler(tsGroups_SizeChanged);
Bind();
}

why the Constructors most add "this.tsGroups.SizeChanged" event?
I chage it like this:
public ExListView()
{
InitializeComponent();
this.SizeChanged += new ventHandler(ExListView_SizeChanged);
Bind();
}
but when i found the toolstrip of this control is shorter?
puzzled :(Confused
AnswerRe: A Question
Kel_
10:47 15 Sep '06  
Hello!

Firstly, thank you, you just helped me figure out the logic error in the control. Smile
I haven't changed AutoSize property of ToolStrip to false, so that's why it was shorter. So, SizeChanged event was somehow overriding AutoSize property...

Now, if you change AutoSize property of tsGroups on false, you can edit the constructor like this :

        public ExListView()
{
InitializeComponent();
Bind();
}

and Bind() like that:

pre lang=cs
protected virtual void Bind()
{
if (m_GroupsGUIs)
{
if (this.tsGroups.Visible==false)
this.tsGroups.Visible = true;
this.tsGroups.Parent = this.Parent;
this.tsGroups.Location = new Point(this.Location.X, this.Location.Y - 25);

if(tsGroups.Width != this.Width)
this.tsGroups.Width = this.Width;
}
else
{
if (this.tsGroups.Visible)
this.tsGroups.Visible = false;
}
}

I'm uploading corrected version, thank you Smile


-- Everything is possible, even the impossible! ^_^

GeneralRe: A Question
phonefans
17:52 15 Sep '06  
hehe,
just Autosize property,why i can't found itSmile
thank youLaugh
GeneralThanks but there is no group if listview is full dock
jvhow
21:59 5 Sep '06  
Thanks for your nice article. It would be so cool if the "groupby" tabstrip could be kept when extended listview is set fill dock to another control (ex: panel). Could it be done?

jvhow

GeneralRe: Thanks but there is no group if listview is full dock
Kel_
23:00 5 Sep '06  
Sure, just tested it Smile

Just add this override to ExListView class, I'll upload the code with this change later today Smile


public override DockStyle Dock
{
get { return base.Dock; }
set {
base.Dock = value;
if (value == DockStyle.Fill || value == DockStyle.Top)
{
tsGroups.Dock = DockStyle.Top;
}
else {
tsGroups.Dock = DockStyle.None;
}
}
}




-- Everything is possible, even the impossible! ^_^

GeneralI think its great.
ilovthecov
2:16 29 Aug '06  
I think its great for you to share this work, I appreciate your effort and desire to let others learn... Have good fortune in all you do.
Thanks.
GeneralRe: I think its great.
Kel_
2:24 29 Aug '06  
Thank you very much! Smile


-- Everything is possible, even the impossible! ^_^

Generaltree diagram produced by ?
BillWoodruff
2:11 26 Aug '06  
http://www.codeproject.com/useritems/GroupableListView/cd.png

May I ask you how you produced this diagram ?

thanks, Bill

"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis

GeneralRe: tree diagram produced by ?
Kel_
6:51 26 Aug '06  
In visual studio 2005, add new item... -> "Class Diagram"
Then just drag & drop some classes of your solution viewer into it, or create new ones directly in Class Diagram.



-- Everything is possible, even the impossible! ^_^

GeneralWhy this code ????
DotNET74
8:04 22 Aug '06  
The VS.NET 2005 ListView already have this property !!!!


GeneralRe: Why this code ????
Steven Roebert
12:07 22 Aug '06  
Yeh it does, but only to visualise the groups, you still have to set the groups for every listviewitem and that is what this code does
GeneralReturn of Groupable ListView ....?
Mahesh Sapre
21:29 20 Aug '06  
As soon as I saw the image in this article, I remembered I have seen something similar to this. I found it here http://codeproject.com/cs/miscctrl/GroupListView.asp[^].

I wonder if anybody can find out the differences between the two articles. Big Grin


Last Updated 15 Sep 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010