Home » Tutorials » Third-Party-Komponenten » VirtualTreeView

VirtualTreeView

Nodes sortieren

Der Baum gestaltet das Sortieren von Nodes schon sehr einfach. Durch den Aufruf der Methode SortTree wird der Baum soriert. Ein Aufruf könnte so aussehen:

vst.SortTree(0, sdAscending, True);

Der erste Parameter gibt die Spalte an, die sortiert werden soll. Der zweite Parameter gibt die Richtung der Sortierung an. sdAscending steht für eine Aufwärts-Sortierung (A -> Z), sdDescending für eine abwärts orientierte Sortierung ( Z -> A). Der dritte Parameter ist optional und hat standardmäßig den Wert True.

Damit der Soriervorgang erfolgreich abläuft muss noch eine Vergleichsprocedure implementiert werden. Dazu stellt der Tree das Ereignis OnCompareNodes zur Verfügung:

procedure TForm1.vstCompareNodes(Sender: TBaseVirtualTree; Node1,
 Node2: PVirtualNode; Column: Integer; var Result: Integer);

Bei Node1 und Node2 handelt es sich um Zeiger auf die zu vergleichenden Nodes. Column hat den Wert der Spalte und dem Referenzparamter wird die Handlungsanweisung übergeben.

Soll Node1 vor Node2 stehen, muss Result einen Wert kleiner als 0 haben. Sind beide Werte identisch, muss Result auf 0 gesetzt werden, und falls Node2 größer als Node1 ist, bekommt Result einen Wert >0.

Ein Beispiel

Zuerst fügen wir dem Baum ein paar Nodes hinzu und hängen folgenden Record dran:

type
  PTreeData = ^TTreeData;
  TTreeData = record
    TestStr: String;
 end;

Die Variable TestStr ist unsere Vergleichsvariable, die wir auch als Beschriftung der Nodes anzeigen. Wie das geht sollte aus den voran gegangenen Kapiteln ersichtlich sein.

Erstelle einen Ereignis-Handler für das OnCompareNodes-Event und bestücke es mit folgendem Quelltext:

procedure TForm1.vstCompareNodes(Sender: TBaseVirtualTree; Node1,
 Node2: PVirtualNode; Column: Integer; var Result: Integer);
var
  Data1: PTreeData;
  Data2: PTreeData;
begin
  Data1:=vst.GetNodeData(Node1);
  Data2:=vst.GetNodeData(Node2);
  if (not Assigned(Data1)) or (not Assigned(Data2)) then
    Result:=0
  else
    Result:=CompareText(Data1.TestStr, Data2.TestStr);
end;

Was passiert hier? Zuerst werden sich die Daten der beiden zu vergleichenden Nodes, die als Parameter übergeben werden, geholt. Dies geschieht über die Methode GetNodeData. Wir benötigen diese Daten, um an unsere Vergleichsvariable TestStr heran zu kommen. Die folgende If-Anweisung prüft, ob die Daten überhaupt vorhanden sind. Ist dies nicht der Fall würde es früher oder später crashen.

Wichtig ist die letzte Zeile. Die Routine CompareText vergleicht zwei Strings und liefert passenderweise direkt unsere benötigten Werte für Result zurück (>0, wenn der erste Wert größer dem zweitem ist; 0, wenn beide Werte identisch sind, ansonsten <0). Die Routine erwartet als Parameter zwei zu vergleichende Strings. In unserem Falle Data1.TestStr (vom ersten Node) und Data2.TestStr (vom zweiten Node).

Jetzt müssen wir dem Baum nur noch die Anweisung geben, seine Nodes zu sortieren. Dies geschieht über die oben erwähnte Routine SortTree. Um zu erfahren, auf welche Spalte der Anwender geklickt hat, stellt das Ereignis den Parameter Column bereit, der die Index-Nummer der Spalte enthält. Über eine Case-Abfrage kann so auf jede Spalte reagiert werden. In unserem Beispiel werden immer die Strings TestStr verglichen, egal auf welche Spalte geklickt wurde.

Ein komplettes Beispiel kannst Du dir hier runterladen.

Häufig werden die einzelnen Spalten durch Klick auf die jeweilige Spalte auf- bzw. abwärts sortiert. Um dies zu realisieren muss nur das OnHeaderClick-Ereignis des Trees ein wenig modifiziert werden:

procedure TMainForm.vstThreadsHeaderClick(Sender: TVTHeader;
 Column: TColumnIndex; Button: TMouseButton; Shift: TShiftState; X,
 Y: Integer);
begin
  vst.SortTree(Column,Sender.SortDirection,True);
  if Sender.SortDirection=sdAscending then
    Sender.SortDirection:=sdDescending
  else
    Sender.SortDirection:=sdAscending
end;

Die Eigenschaft SortDirection der Headerzeile gibt die Sortierrichtung an, die nach jedem Klick umgekehrt werden muss.