Author: Ernesto De Spirito
How to sort a ListView in ascending or descending order by a given column?
Answer:
Solve 1:
We want the following behaviour for a ListView:
When the user clicks on a column header, the ListView should be sorted by that
column
The initial sort order should be ascending. If the user clicks on the same column
again, the sort order should be toggled. If the user clicks on another column, the
sort order of the new column should be the same as the last sorted column.
For the implementation we need two variables to hold the last column clicked by the
user and the current sort order:
1 var2 LastSortedColumn: integer;
3 Ascending: boolean;
4 5 We can initialize them when the form is created:
6 7 procedure TForm1.FormCreate(Sender: TObject);
8 begin9 LastSortedColumn := -1;
10 Ascending := True;
11 end;
12 13 in the ColumnClick event of the ListView we determine the sort order and perform
14 the sort:
15 16 procedure TForm1.ListView1ColumnClick(Sender: TObject;
17 Column: TListColumn);
18 begin19 if Column.Index = LastSortedColumn then20 Ascending := not Ascending
21 else22 LastSortedColumn := Column.Index;
23 TListView(Sender).CustomSort(@SortByColumn, Column.Index);
24 end;
SortByColumn is a function that should be previously declared and is the function
used by CustomSort to compare two items. The value passed to the Data parameter of
CustomSort will be passed as the Data parameter to SortByColumn and we use it for
the sort column:
25 26 function SortByColumn(Item1, Item2: TListItem; Data: integer):
27 integer; stdcall;
28 begin29 if Data = 0 then30 Result := AnsiCompareText(Item1.Caption, Item2.Caption)
31 else32 Result := AnsiCompareText(Item1.SubItems[Data - 1],
33 Item2.SubItems[Data - 1]);
34 ifnot Ascending then35 Result := -Result;
36 end;
Solve 2:
Instead of calling the custum sort procedure we also can use the OnColumnClick and
the OnCompare events ion conjunction... That way the compare routine is kept within
the class, here a TForm decedant.
Like this:
37 38 procedure TfrmMain.lvThingyColumnClick(Sender: TObject; Column: TListColumn);
39 begin40 if Column.Index = fColumnClicked then41 fSortAscending := not fSortAscending
42 else43 begin44 fSortAscending := true;
45 fColumnClicked := Column.Index;
46 end; // else47 48 Screen.Cursor := crHourglass;
49 try50 (Sender as TListView).AlphaSort;
51 finally52 Screen.Cursor := crDefault;
53 end; // try54 end;
55 56 procedure TfrmMain.lvThingyCompare(Sender: TObject; Item1, Item2: TListItem; Data:
57 Integer; var Compare: Integer);
58 begin59 case fColumnClicked of60 0: Compare := CompareStr(Item1.Caption, Item2.Caption);
61 else62 Compare := CompareStr(Item1.SubItems[fColumnClicked - 1],
63 Item2.SubItems[fColumnClicked - 1]);
64 end; // case65 ifnot fSortAscending then66 Compare := -Compare;
67 end;