Este artículo explica cómo ordenar un ListView usando la propiedad Sorted, el evento OnCompare o una función de ordenamiento con CustomSort

Ordenando un TListView

Copyright © 2000 Ernesto De Spirito

LMD-Tools 6.1 - 300+ componentes para varias tareas de desarrollo!

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).

JfControls Library - para Delphi y C++ Builder