2012-12-26 5 views
6

Ho una vista ad albero che è già popolata con file/cartelle da un'altra procedura. Mi piacerebbe iterare uno ad uno attraverso gli elementi nella vista ad albero, andando nell'ordine esatto da cima a fondo. Tuttavia, a differenza di un elenco normale, non posso utilizzare solo una semplice dichiarazione for per questo. Devo andare in ogni nodo, ecc.Iterare in modo ricorsivo attraverso i nodi in una vista ad albero?

Come faccio? Spero che ci sia un modo per farlo senza eseguire una procedura ricorsiva. Mentre eseguo l'iterazione di questi elementi, non mi interessa necessariamente i nodi padre o figlio di quello attualmente focalizzato. Devo solo essere in grado di leggere la proprietà Data di ogni nodo mentre li passo, oltre a evidenziare quello corrente nella vista ad albero mentre lo percorro. Per ogni elemento in questa vista ad albero, eseguirò un po 'di lavoro e voglio visualizzare visivamente all'utente quale è attualmente selezionato durante questo processo.

+0

"Non posso usare solo una semplice istruzione per questo" <- Ho problemi a capire perché? si suppone che si usi una funzione/procedura ricorsiva con un ** per ** loop nel suo corpo, dopo che il ** for loop ** si agisce sulla proprietà Node.Data e il chiamante passerà al nodo successivo e così via ... – ComputerSaysNo

+1

Ho detto che non posso usare una semplice istruzione ** for ** per questo, perché non esiste una cosa come un indice oggetto o un numero totale di nodi in una vista ad albero. –

+0

L'intera ragione che sto chiedendo è perché sto cercando di evitare di chiamare effettivamente questa stessa procedura in modo ricorsivo, preferirei avere solo un ciclo 0..MAX-1 senza ricorsione, ma non penso sia possibile e mi piacerebbe esserne sicuro. –

risposta

16

In effetti è possibile utilizzare un ciclo for.

var 
    Node: TTreeNode; 
.... 
for Node in TreeView.Items do 
    DoSomething(Node); 

Questo è zucchero sintattico per:

for i := 0 to TreeView.Items.Count-1 do 
    DoSomething(TreeView.Items[i]); 

in termini di leggibilità mi sento di raccomandare il ciclo for/in.

Nelle versioni Delphi precedenti che non supportano l'iteratore di nodo è preferibile eseguirlo con un ciclo while.

Node := TreeView.Items.GetFirstNode; 
while Assigned(Node) do 
begin 
    DoSomething(Node); 
    Node := Node.GetNext; 
end; 

Mi aspetto che ci siano altri modi per farlo. Questi sono gli unici che conosco!


LU RD rende interessante osservazione che i documentation stati:

Accesso vista albero elementi di indice può essere tempo ad alta intensità, soprattutto quando la vista albero ha molti elementi. Per prestazioni ottimali, prova a progettare l'applicazione in modo che abbia il minor numero possibile di dipendenze sull'indice di visualizzazione della struttura ad albero.

Questo è assolutamente vero. Per l'accesso casuale, il codice deve percorrere l'albero, iniziando dalla radice, finché non si trova il nodo i th.

Tuttavia, esiste un ottimizzazione per l'accesso sequenziale. Il wrapper di visualizzazione ad albero Delphi ricorda l'indice dell'ultimo nodo localizzato per indice. La prossima volta che si richiede un nodo con indice non più di uno diverso dal nodo memorizzato nella cache, il nodo richiesto può essere restituito rapidamente. Questo è implementato in TTreeNodes.GetNodeFromIndex.

+0

NICE e io non avremmo mai pensato che fosse possibile. –

+0

+1 non sapevo mai che fosse possibile esaminare tutti gli elementi in un ciclo ... – ComputerSaysNo

+0

+1 bel arrotondamento del post iniziale ... – bummi

3
var 
i:Integer; 
begin 
    for I := 0 to tv.Items.Count - 1 do 
     begin 
     Listbox1.Items.Add(tv.Items[i].Text +' SubItems: ' + IntToStr(tv.Items[i].Count)) 
     end; 

end; 
+0

Questo solo fa il primo livello di gerarchia, non tutti i sottotitoli –

+3

@Jerry No, questo li enumera tutti –

+0

... Sono confuso quindi, mi dispiace per il salto alle conclusioni –