Einzelnen Beitrag anzeigen

Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#1

TreeView-Nodes anhand Pfad-String finden (zu langsam)

  Alt 5. Mär 2009, 13:14
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
  Mit Zitat antworten Zitat