Click here to Skip to main content
Click here to Skip to main content

Adding Multicolumn-sorting to ListViewSortManager

, 5 Dec 2007
Rate this:
Please Sign up or sign in to vote.
Easily add multicolumn sorting to your ListView controls

Introduction

A long time ago (back in 2002), Eddie Velazquez published a little class to easily add column sorting to ListView controls. The original article is here.

Several people (myself among them) requested some other features, especially the ability to sort by multiple columns at the same time. Although he fixed some bugs, Eddie did not have the time to add this bigger feature. One day I really needed it for a project and instead of waiting, I decided to roll up my sleeves and do it.

I had wanted to post it here for everyone else to benefit, but I had not given myself the time to write the article. But finally, here it is.

The most important feature I added to Eddie's version is multicolumn sorting. But I also added:

  • Currency and IP address sorting. The IP sorter was taken from a comment by Eddie in the original article.
  • Fixed a bug with the SortEnabled property
  • ListViewBottomItem class for items that should always stay at the bottom (e.g. a total row).

To sort on several columns at once, click the first column, then hold down the Ctrl key and click on additional columns.

The demo project included with this article is for Visual Studio .NET 2003 and .NET 1.1, so it can reach a broader audience. I have used this class also with Visual Studio 2005 and .NET 2.0 and everything works fine as is.

Using the Code

I have tried to keep my version backward compatible with Eddie's, and I have succeeded in 99% of the cases. Using ListViewSortManager is very easy. You just have to create an instance in your constructor, set the list view and column sorters, and that's it. In the example below, I have marked in bold the required changes:

using Intelectix.Windows.Forms;

class MyForm()
{
    ListView lstNames;
    ListViewSortManager sortManager;

    public MyForm()
    {
        InitializeComponent();

        sortManager = new ListViewSortManager(lstNames,  new Type[]
            {
                typeof(ListViewTextSort),
                typeof(ListViewTextSort),
                typeof(ListViewInt32Sort),
                typeof(ListViewDateSort)
            });
    }
}

Simple, isn't it? If you want to specify initial sorting to the list, specify the column index in the third parameter of the constructor, and the sort order in the fourth parameter:

sortManager = new ListViewSortManager(lstNames,  new Type[]
    {
        typeof(ListViewTextSort),
        typeof(ListViewTextSort),
        typeof(ListViewInt32Sort),
        typeof(ListViewDateSort)
    }, 1, SortOrder.Descending);  // Sort descending by second column

Of course, you will have to add the ListViewSortManager.cs file to your project.

Adding Items to the ListView

If you are adding a large quantity of items to the listview, either use ListView.Items.AddRange or disable ListViewSortManager. If you add one by one, the list view will be sorted after each item and you will see a performance hit.

lstNames.BeginUpdate();
lstNames.Items.Clear();
sortManager.SortEnabled = false;

for(int i = 0; i < 1000; i++)
{
    ListViewItem item = new ListViewItem();
        .
        .
        .
    lstNames.Items.Add(item);
}

sortManager.SortEnabled = true;
lstNames.EndUpdate();

Creating your Own Comparers

I have provided comparers for:

  • Text (ListViewTextSort)
  • Case insensitive text (ListViewTextCaseInsensitiveSort)
  • Date (ListViewDateSort)
  • Integers (ListViewInt32Sort, ListViewInt64Sort)
  • Double (ListViewDoubleSort)
  • Currency (ListViewCurrencySort)
  • Percentage (ListViewPercentSort)
  • IP addresses (ListViewIPSort)

If you want to sort on something different, implementing your own comparer is very easy (I've made it easier, but a little different than Eddie's version). You just need to implement the IListViewSorter interface, and compare two items. Below you can see the code for ListViewCurrencySort:

public class ListViewCurrencySort : IListViewSorter
{
    public int Compare(String lhs, String rhs)
    {
        decimal result =
           decimal.Parse(lhs, NumberStyles.Currency, CultureInfo.CurrentCulture) -
           decimal.Parse(rhs, NumberStyles.Currency, CultureInfo.CurrentCulture);

        if(result > 0)
            return 1;
        else if(result < 0)
            return -1;
        else
            return 0;
    }
}

Other Improvements

There is a ListViewBottomItem, that when sorted, will always go at the very bottom. This is useful for rows containing totals. It is created and used like a regular ListViewItem (some constructors are missing, though).

How Multicolumn Sorting Works

Basically, to support sorting by multiple columns, the ListViewSortManager keeps a list of the indexes of sorted columns.

When the user clicks a column:

  • If the Control key is not down, the listView_ColumnClick method checks to see if the same column is already the first in the sequence, and if so, just toggles the order. Otherwise, the whole sort list is cleared and then the column added.
  • If the Control key is down, the clicked column is added at the end of the sort sequence. If it was at the end before, its sort order is toggled. If it appeared somewhere in the middle of the sequence, it is removed from there and added at the end.

The sequence contains the indexes of the columns in the order they should be sorted. If the index is negative, it means the column should be sorted in a descending manner.

Coming Soon

One thing I have always wanted to add is designer support. I visualize it like this:

  • In the designer, add a component to your form.
  • Each listview gets SortEnabled, SortColumn, and SortOrder properties which you can set.
  • In the column designer, each column gets a Sorter property.

I just hope the "Soon" in this section's title is soon enough. Smile | :)

If you have any doubts, comments, or improvements, feel free to use the message board below so everyone can benefit.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

I graduated from Monterrey Institute of Technology in December 2003 with a degree in Electrical Engineering, of which I mostly remember nothing!
 
I have been programming since I was 10 when I learned QuickBasic. I have experience in C/C++, MFC, Win32, Visual Basic (don't tell anyone!), HTML, ASP, and recently in C# (which I like very much BTW), ASP.NET, and ADO.NET/SQL Server.
 
Now that I have to work, I'm currently the president of Intelectix, my own little company, that I founded in June 2004, where we do contract work in software development (and a little web design and hosting), specializing in .NET. I even already have four other people working with me, very good all of them!
 
Having some big projects already, we've been doing very good, so good in fact that only recently we finished our web site (which currently is only in Spanish -- English version coming soon!)
 
I have special interests in cars (Audi, Formula 1) and golf -- I used to be good at it (at one point a +2, now a 6 handicap on the board, but playing much worse than that.)

Comments and Discussions

 
QuestionSorting multicolumns programmatically Pinmemberjjangli28-Jul-11 3:56 
AnswerRe: Sorting multicolumns programmatically PinmemberLuis Alonso Ramos3-Aug-11 4:44 
SuggestionRe: Sorting multicolumns programmatically [modified] PinmemberGreg Koweiski26-Oct-11 19:39 
GeneralRe: Sorting multicolumns programmatically PinmemberLuis Alonso Ramos28-Oct-11 13:11 
Generalhelp me Pinmemberchoti720-May-11 5:17 
GeneralRe: help me PinmemberLuis Alonso Ramos20-May-11 6:04 
GeneralRe: help me Pinmemberchoti720-May-11 6:13 
GeneralMissing Images (in additional TreeView Control) PinmemberKSchweiger3-Dec-08 9:55 
QuestionAlternatives? PinmemberGavin Roberts16-Sep-08 22:35 
AnswerRe: Alternatives? PinmemberLuis Alonso Ramos17-Sep-08 3:55 
GeneralRe: Alternatives? PinmemberGavin Roberts17-Sep-08 4:15 
GeneralRe: Alternatives? PinmemberLuis Alonso Ramos17-Sep-08 5:42 
GeneralRe: Alternatives? PinmemberGavin Roberts17-Sep-08 5:49 
GeneralQuestion on License PinmemberRyan Dunn6-Apr-08 13:02 
GeneralRe: Question on License PinmemberLuis Alonso Ramos7-Apr-08 6:10 
GeneralDesigner support available! PinmemberLuis Alonso Ramos10-Feb-08 18:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 6 Dec 2007
Article Copyright 2007 by Luis Alonso Ramos
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid