|
Ordenando un TListView
Copyright © 2000 Ernesto
De Spirito
Ordenando por la primera columna
Ordenar un TListView por la primera columna es fácil:
ListView1.SortType := stText;
Estableciendo SortType a stText es más o menos como
establecer Sorted a True en un objeto TListBox.
La lista será ordenada y permanecerá ordenada después de agregados y
modificaciones, hasta que SortType sea establecida de vuelta
a stNone:
ListView1.SortType := stNone;
...que es como establecer Sorted a False en un
objeto TListBox. No deshará el ordenamiento, pero futuros
agregados y modificaciones de elementos en la lista no serán ordenados.
Ordenando con un evento OnCompare
Para mantener un TListView ordenado por otra columna (o
por datos arbitrarios guardados o referenciados en los
objetos TListItem), deberíamos o escribir un
evento OnCompare o una función ordenadora para usarla con el
método CustomSort.
Si quiere mantener la lista ordenada mientras le agrega y modifica
elementos, entonces debería usar un evento OnCompare.
procedure(Sender: TObject; Item1, Item2: TListItem;
Data: Integer; var Compare: Integer) of object;
El parámetro Compare debería establecerse a 1, - 1 o 0 dependiendo
de si el primer elemento es mayor (o debería situarse después) que el segundo
elemento, si el primer elemento es menor (o debería situarse antes) que el
segundo elemento, o si los dos elemento son iguales, respectivamente.
En el siguiente ejemplo estamos ordenando un TListView por
su cuarta columna (que suponemos representa valores enteros) en orden
descendente:
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;
Ahora que tenemos un evento OnCompare, para ordenar la lista
y mantenerla ordenada, deberíamos establecer SortType a stBoth (en
vez de stText, que ordena por la primera columna sin usar el
evento OnCompare):
ListView1.SortType := stBoth;
Si sólo desea realizar un ordenamiento temporal, puede hacer lo siguiente:
ListView1.SortType := stBoth;
ListView1.SortType := stNone;
o sinó:
ListView1.CustomSort(nil, 0);
Ordenando con una función ordenadora
Si necesita un ordenamiento más veloz, entonces debería escribir una
función ordenadora. Esta función debería devolver 1, - 1 o 0 (como el
parámetro Compare del evento OnCompare que se
discutió arriba). Por ejemplo:
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;
Entonces, cada vez usted quiera ordenar la lista, llame a CustomSort
pasándole la dirección de la función ordenadora. Por ejemplo:
ListView1.CustomSort(@ByFourth, 0);
El parámetro Data del evento OnCompare es 0 si el evento se
llama automáticamente cuando SortType es stData o stBoth,
pero si se genera a causa de un llamado a CustomSort,
entonces su valor es el segundo
parámetro que se pasa a este método. Lo mismo sucede con el
parámetro Data de la función ordenadora, de modo que el
parámetro Data se usa normalmente para especificar la
columna por la que se ordenará (no lo usamos en nuestro ejemplo
para hacerlo sencillo).
|