Ich baue ein TreeView aus einer Datenquelle auf.
Die daten kommen mit zwei Informationen an: Kategorie und Dateninhalt
Die Kategorie ist wie ein Verzeichnis-Pfad aufgebaut: Kategorie\Subkategorie\Datenbeschreibung (bis Level 8 ) und wird damit passend in ein TreeView einsortiert. Leider kommen die Daten nicht nach Kategorie sortiert an, denn dann könnte ich den TreeView "on the fly" aufbauen.
Ich muss also ständig suchen, welcher Node zum PfadString passt, dort einsortieren oder neu anlegen. Dazu schneide ich den Pfad aus (Bsp. Kategorie\Subkategorie\) und übergebe den an die u.a. Funktion "FindNodeByPath". Je nach Rückgabe lege ich nur den Datennode an oder eben die fehlende Kategorien-Nodes.
Delphi-Quellcode:
(***************************************************************************
Funktion, die aus einem Node (mit Parents) ein PathStr bildet
Achtung! aNode-Pointer wird verändert
***************************************************************************)
function GetNodePath(aNode:TTreeNode; WithDelimiter: Boolean): AnsiString;
begin
if WithDelimiter then Result := aNode.Text +'\'
else Result := aNode.Text;
while assigned(aNode.Parent) do begin
aNode := aNode.Parent;
Result := aNode.text + '\' + Result;
end;
end;
(***************************************************************************
Finden einen Node durch Angabe des Pfadnamen
Achtung! aPath-Wert wird verändert
***************************************************************************)
function FindNodeByPath(const aTreeView: TTreeView; aPath: AnsiString): TTreeNode;
var
i : Integer;
begin
Result := NIL;
if Assigned(aTreeView) and (Length(aPath)>0) then begin
// Pfadstring UpperCase und Delimiter anfügen
aPath := AnsiUpperCase(aPath);
if aPath[length(aPath)] <> '\' then aPath := aPath +'\';
// Alle Items aus dem TreeView testen
for i := 0 to aTreeView.Items.Count-1 do begin
// Vergleich, wenn positiv, dann Abbruch der Schleife
if AnsiUpperCase(GetNodePath(aTreeView.Items[i], True)) = aPath then begin
Result := aTreeView.Items[i];
Break;
end;
end;
end;
end;
Das funktioniert auch, wird aber proportional zu Datenmenge immer langsamer. Vor allem weil bei der Methode auch die irrelevanten Daten-Nodes mit geprüft werden.
Kann man das auch schneller lösen?
Meine Ideen bisher:
- Eine StringList parallel nur mit Ordnernamen und Node-Object, die ich dann via IndexOf durchsuche.
- oder Node.Data kennzeichnen, damit ich wenigstens die Daten-Nodes beim Stringvergleich ausklammern kann
Beide Ideen könnte ich selber umsetzen, aber nimmt mir die universelle Eigenschaft von "FindNodeByPath". Deshalb suche ich nach einer Idee, die innerhalb von "GetNodePath" oder "FindNodeByPath" verbessert, ohne jetzt spezielle Vorbereitung der TreeNodes zu fordern.
PS: VirtualTreeView hätte ich mir gerne mal angeschaut, scheint aber nicht für D5 zur Verfügung zu stehen.
PPS: String ist bei D5 noch ein AnsiString