I have decided to kill two birds with one stone in getting to grips both with .Net and Pocket PC development, by writing a project in C# using the .NET Compact Framework.
For this project I need a sortable list view control; no problem I thought - I'll use the one in the .Net Framework. This is when you realise that a lot of the methods and properties in the documentation do not have the magic words "Supported by the .NET Compact Framework", including the ListView.Sort method. So, I decided to roll my own, called SortListView. There may be other similar classes out there, but I treated this as a learning exercise.
As it turned out, this was quite a good choice, as it also required some interop with unmanaged code, something else I am hoping to learn more about.
How to use the
I have tried to make using the
SortListView class as simple as possible.
- In the form designer, drag a
ListView control onto the form, and position and size it as desired. This step is useful purely to set up the Size and Location properties of the
ListView control. If you prefer, you can enter these manually into the code.
- In the Form class constructor, create an
AdrianStanley.Windows.Forms.SortListView control, and a
AdrianStanley.Windows.Forms.SortColumnHeader control for each column you want in the
ListView, and add them to the ListView object's Columns collection.
- Make sure the
View property is set to
- For each
SortColumnHeader object, set its
ColumnHeaderSorter property. This determines how items in the column will sort. The property should be set to an instance of a class derived from
AdrianStanley.Windows.Forms.SortComparer. I have provided a number of such classes (see SortComparer.cs), for sorting strings, integers, doubles, and dates.
- Add items to the
ListView control as normal
- Build the unmanaged dll, ControlEx.dll, for your target platform, and add the dll to the main .Net project. The download includes a build of this dll for Pocket PC 2003.
That should be it. Initially items in the
ListView are unsorted. When you first click on a column header, the items in that column will be sorted in ascending order, and a little upwards pointing arrow will be displayed next to the text in the column header. When you click on the column header again, the arrow changes to point downwards, and the column is sorted in descending order.
To demonstrate how simple this is, here is a complete C# Windows project that creates a sorting ListView with three columns.
public class SortListViewForm : System.Windows.Forms.Form
private AdrianStanley.Windows.Forms.SortListView m_sortListView;
private AdrianStanley.Windows.Forms.SortColumnHeader m_colhdrName;
private AdrianStanley.Windows.Forms.SortColumnHeader m_colhdrAmount;
private AdrianStanley.Windows.Forms.SortColumnHeader m_colhdrDate;
m_sortListView = new AdrianStanley.Windows.Forms.SortListView();
m_colhdrName = new AdrianStanley.Windows.Forms.SortColumnHeader();
m_colhdrDate = new AdrianStanley.Windows.Forms.SortColumnHeader();
m_sortListView.Size = new System.Drawing.Size(248, 272);
m_sortListView.View = System.Windows.Forms.View.Details;
m_colhdrName.Text = "Name";
m_colhdrName.Width = 100;
m_colhdrDate.Text = "Date";
m_colhdrDate.Width = 80;
m_colhdrAmount.Text = "Amount";
m_colhdrAmount.Width = 60;
m_colhdrAmount.TextAlign = HorizontalAlignment.Right;
Text = "SortListView Demo";
m_colhdrName.ColumnHeaderSorter = new ComparerString();
m_colhdrDate.ColumnHeaderSorter = new ComparerStringAsDateTime();
m_colhdrAmount.ColumnHeaderSorter = new ComparerStringAsDouble();
AddItem("Green, David", new DateTime(2001, 12, 31), 100.23);
AddItem("Brown, Tom", new DateTime(2000, 4, 3), 56.98);
AddItem("Pink, Jane", new DateTime(1996, 6, 15), 653.18);
AddItem("White, Sarah", new DateTime(2006, 8, 23), 345.22);
AddItem("Grey, Richard", new DateTime(2003, 9, 18), 27.74);
private void AddItem(string name, DateTime date, double amount)
string displayInfo = new string;
displayInfo = name;
displayInfo = date.ToString("d");
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalDigits = 2;
displayInfo = amount.ToString("N", nfi);
protected override void Dispose( bool disposing )
base.Dispose( disposing );
static void Main()
SortListView class can persist state if desired. The persisted state consists of the index of the current sort column, and the sort order for each column. The persistance mechanism uses the
OpenNETCF.Win32 namespace, available from http://www.opennetcf.org/. The persistance mechanism is disabled by default, as not everyone will have the
OpenNETCF.Win32 namespace. To enable the persistance mechanism, define the preprocessor constant
PERSIST_SORTLISTVIEW in the project settings, set the
SortListView.PersistKeyName property to the key to be used in the registry for persisting values, and then call the
SaveState methods to respectively load the state from the registry, and to save the state to the registry.
I recommend that a value of the form "SOFTWARE\CompanyName\ProductName\ListViewName" is used for the
The Main Classes
There are three main classes involved in this project. I have used the XML comments feature of the .Net development environment to document the classes, so for detailed information I suggest you read that - preferably after generating the HTML files (Tools, Build Comment Web Pages...).
SortListView class represents a Windows list view control, which displays a collection of sorted items in a details view. The
SortListView class extends the existing .Net Compact Framework ListView class, when it is used in a details view, with
ListView.View set to
View.Details. In details view, the
ListView control has a column header. The
SortListView class will automatically sort the items in the ListView control when a column header is clicked.
When a column header is clicked for the first time, the items in the column are sorted in ascending order. The column is now the sorted column; the ordering of items in the other columns follow the ordering of the items in the clicked column. Clicking the column header again will sort the items in the column in descending order. A sort arrow is shown in the column header to show the direction of the sort - an upwards pointing arrow for ascending order, and a downwards pointing arrow for descending order. By default the sort arrow is shown to the right of any text in the column header. If the column header text is aligned to the right then the sort arrow will be shown to the left of the text.
Each column has its own sort order, and its own comparer for determining how items in the column should be sorted. The sort order is defined as one of the values in the enum
AdrianStanley.Windows.Forms.SortOrder, and the comparer is defined as an instance of a class derived from
AdrianStanley.Windows.Forms namespace defines some existing comparers for sorting
SortListView class requires unmanaged code (contained in ControlEx.dll) to show the sort arrow within the column header.
SortColumnHeader class sisplays a single column in a
SortListView control, and represents a column header in a
A column header is an item in a
SortListView control that contains heading text, and a sort order.
SortColumnHeader objects can be added to a
SortListView using the
Add method of the base
SortColumnHeader provides the
Sorting property to set the sort order for the column, and the
SortComparer property to set the comparer to be used to sort items in the column.
SortComparer class is used in conjunction with the
SortListView.Sort method, and provides a way to customize the sort order of items in a
The class is marked as abstract, as it acts as a base class for derived classes which implement the
Several classes derived from
SortComparer are provided:
ComparerString. Compares alphabetic strings.
CompareStringAsShort. Compares shorts represented as strings.
CompareStringAsInt. Compares integers represented as strings.
CompareStringAsLong. Compares longs represented as strings.
CompareStringAsDouble. Compares doubles represented as strings.
CompareStringAsDateTime. Compares dates represented as strings.