|
Sorting a TListView
Copyright © 2000 Ernesto
De Spirito
Sorting by the first column
Sorting a TListView by the first column is easy:
ListView1.SortType := stText;
Setting SortType to stText is more or less like
setting Sorted to True in a TListBox object.
The list will be sorted and will remain sorted after additions
and modifications, until SortType is set back
to stNone:
ListView1.SortType := stNone;
It's like setting Sorted to False in
a TListBox object. It won't undo the sorting, but
future additions and modifications to the items list won't be
sorted.
Sorting with an OnCompare event
To have a TListView sorted on another column (or arbitrary data stored
or referenced in TListItem objects), we should either write
an OnCompare event or an ordering function to be used with
the CustomSort method.
If you want to sort keep a list sorted while adding and modifying items, then
you should use an OnCompare event.
procedure(Sender: TObject; Item1, Item2: TListItem;
Data: Integer; var Compare: Integer) of object;
The parameter Compare which is passed by reference should be set
to 1, -1 or 0 depending on whether the first item is greater than (or
should be placed after) the second item, the first item is lower than
(or should be placed before) the second item, or if the two items are
equal, respectively.
In the following example we are sorting a TListView by its fourth
column (wich represents integer values) in descending order:
procedure TForm1.ListView1Compare(Sender: TObject; Item1,
Item2: TListItem; Data: Integer; var Compare: Integer);
var
n1, n2: integer;
begin
n1 := StrToInt(Item1.SubItems[2]);
n2 := StrToInt(Item2.SubItems[2]);
if n1 > n2 then
Compare := -1
else if n1 < n2 then
Compare := 1
else
Compare := 0;
end;
Now that we have an OnCompare event, to sort the list and
having sorted, we should set SortType to stBoth (instead
of stText, that sorts by the first column without using
the OnCompare event):
ListView1.SortType := stBoth;
If you just want to perform a temporal sort, you can do the following:
ListView1.SortType := stBoth;
ListView1.SortType := stNone;
or else:
ListView1.CustomSort(nil, 0);
Sorting with an ordering function
If you need a faster sort, then you should write an ordering function.
This function should return 1, -1 or 0 (like the Compare parameter of
the OnCompare event discussed above). For example:
function ByFourth(Item1, Item2: TListItem; Data: integer):
integer; stdcall;
var
n1, n2: cardinal;
begin
n1 := StrToInt(Item1.SubItems[2]);
n2 := StrToInt(Item2.SubItems[2]);
if n1 > n2 then
Result := -1
else if n1 < n2 then
Result := 1
else
Result := 0;
end;
Then, every time you want to sort the list, you
call CustomSort passing the address of the ordering function.
For example:
ListView1.CustomSort(@ByFourth, 0);
The Data parameter of the OnCompare event is 0
if the event is called automatically
when SortType is stData or stBoth,
but if it is generated because of a call to CustomSort, then
its value is the second parameter to this method. The same happens with
the Data parameter of the ordering function, so the Data parameter
is normally used to specify a column to sort (we didn't use it in our example
to make it simple).
|