Newsgroup: it.comp.lang.visual-basic
Titolo: [?] "Fotografare" la struttura di un TreeView

Uso il controllo TreeView per mostrare una certa struttura. Tramite apposite
istruzioni l'operatore puň cambiare questa struttura, ovvero spostare gli
elementi in verticale e anche cambiando l'appartenenza ai nodi.
Alla fine devo registrare la nuova struttura _esattamente_ come visivamente
mostrata, cioč rispettando gli ordinamenti e le appartenenze come
modificate.
Non ho trovato nulla che mi consenta di analizzare la struttura in modo
sequenziale cosě come visivamente modificata e mostrata (gli Index non
cambiano dopo uno spostamento).
La domanda č: Possibile che debba seguire tutta la logica dei vari <First
Last>Sibling, Child, Next, Previous e compagnia bella? Pensando ai vari nodi
con un numero indefinito di sottonodi e elementi, diventa una palla mica da
ridere... :-(
Grazie.

 ridere... :-(
Dovrebbe essere piů semplice di quello che sembra :)
Per fotografarla basta un bel loop e ad es. salvi il percorso completo di
ogni nodo su disco.
Es.
Paperopoli
|
+ Paperi
|    |
|    + Paperino
|    + Paperone
|
+ Bassotti
    |
    + 176-716
    + 167-617
diventa
Paperopoli
Paperopoli\Paperi
Paperopoli\Paperi\Paperino
Paperopoli\Paperi\Paperone
Paperopoli\Bassotti\
Paperopoli\Bassotti\176-716
Paperopoli\Bassotti\167-617
Adesso per rileggerlo, rileggi una riga alla volta, la spezzi sul separatore
con Split() e chiami una funzioncina con gestione d'errore che ti inserisca
ogni pezzo all'albero.
es.
Paperopoli\Paperi --> Paperopoli, Paperi
Aggiungo Paperopoli
Aggiungo Paperi a Paperopoli
Ciao
--
Math Parser : 
http://www.neodatatype.net
Sito Comune : 
http://www.it-lang-vb.net

ti riporto il codice per la visita di un albero, anzi, lo pseudo codice, sai
com'è non ho mai avuto a che fare con il treeview e non so quali sono le
proprietà...
allora:
private sub visita (<posizione attuale nell'albero> [come parametro che
chiamerò P]
if not<fine albero> then
  operazione desiderata su P
  for i=0 to <numero di sottoalberi/sottodirectory dalla posizione corrente
P>-1 'Se non puoi stabilire il numero di sottoalberi, inventa un ciclo
equivalente
     visita(Pi)    'Pi è il sottoalbero/sottodirectory che stai considerando
  next i
end if
come avrai notato questa procedura è ricorsiva, quindi fai attenzione.
Questo è un codice che ho studiato a scuola per la visita negli alberi
binari di ricerca, ma con il ciclo for è adattato al'abero generico.
Originariamente era, (utilizzavo i puntatori ai nodi nella gestione dinamica
della memoria, ma non so se in VB esistono :))
Type
 AlBin= ^nodo
nodo=Record
              info: t (tipo generico)
              s, d: albin                     'ho già detto che si trattava
di alberi binari quindi con solo 2 figli per ogni nodo
           end;
Var
 B: albin
Visita_Anticipata (B)
   if B<>Nil then
                    operazione su B^.info
                    visita_anticipata(B^.s)
                    visita_anticipata(B^.d)
   end if
Non fare caso alla sintassi, poichè ti ho scritto un misto di Turbo Pascal e
Visual Basic :)
Cmq spero di esserti stato utile.

 ridere... :-(
Ricordo di un file scaricato tempo fa da internet, presumo di averlo
cancellato,
dove salvava la struttura parentale in un file.txt e all'occorrenza lo
ricaricava.
La Proprietà Parent dovrebbe aiutarti
Ave
giuseppeD

[*Lupo* = 
LupoOrmaiR...@libero.it
 in
news:bng70p$10mrt2$
1...@ID-174464.news.uni-berlin.de
] ha scritto:
Grazie a tutti, ma ho risolto componendomi un vettore e poi analizzando lo
stesso, come segue (tv è il controllo TreeView):
    Dim nd as Node
'       Compone vettore per l'analisi in sequenza
    ReDim vettore_sequenza(0 To 0)
'       Esegue prima per il nodo principale e unico
    For Each nd In tv.Nodes
        If nd.Parent Is Nothing Then
            ReDim Preserve vettore_sequenza(0 To UBound(vettore_sequenza) +
1)
            vettore_sequenza(UBound(vettore_sequenza)) = nd.Key
            Exit For
        End If
    Next nd
'       Esegue ora per tutti i nodi con figli, comprendendo il libro e
quindi i suoi figli
    For Each nd In tv.Nodes
        If nd.Children Then
'               Ha figli
'               Parte dal primo e assegna la sequenza a tutti i fratelli di
questo stesso nodo
            Set nd = nd.Child.FirstSibling
            Do
                ReDim Preserve vettore_sequenza(0 To
UBound(vettore_sequenza) + 1)
                vettore_sequenza(UBound(vettore_sequenza)) = nd.Key
                If nd.LastSibling Is nd Then Exit Do
                Set nd = nd.Next
            Loop
        End If
    Next nd
Poi:
    For n_sequenza = 1 to UBound(vettore_sequenza)
        Set nd = tv.Nodes(vettore_sequenza(n_sequenza))
'        ...
    Next n_sequenza

 completo di ogni nodo su disco.
Ma io non ho il percorso completo di ogni nodo, non si tratta di un "Esplora
Risorse". ;-)
Sto scrivendo un programma che consente di scrivere un "libro", un po' come
un HTML editor, o un HELP workshop, chiaramente senza necessità di un
compilatore. Per cui per ogni nodo/argomento/parte (a qualsiasi livello) ho
solo il suo titolo (che poi per me è la chiave, univoca, per ora non è una
limitazione che due titoli non possano ripetersi in tutto il libro). Grazie
al Parent ho anche il titolo/chiave del nodo di appartenenza, ma niente di
più. Vedi comunque come ho risolto nel post sotto.

 completo di ogni nodo su disco.
Scusa la postilla, ma solo per evidenziare che quel che dici ed esemplifichi
è vero se la struttura è appena stata costruita. In questo caso un loop per
i vari nodi dovrebbe (non ho ri-verificato) ciclarli nello stesso ordine
fisico/grafico.
Se però sposti fisicamente un elemento, lo stesso loop (che penso si basi
sull'Index, che non cambia) ti restituirà le informazioni nello stesso
ordine di prima, quello di costruzione diversi, appunto, dall'attuale
fisico/grafico.
Inoltre, anche giocando per ogni nodo con il suo Parent e il Parent del
Parent (e così via) si può ricostruire il percorso completo (come se fosse,
appunto, un esplora risorse), ma questo non ha nulla a che fare con la
sequenza grafica (magari modificata) del treeview allo stato attruale.

 sequenza grafica (magari modificata) del treeview allo stato attruale.
Io proprio per questo motivo come chiave di un nodo in genere uso proprio il
percorso completo del nodo, proprio perchè identifica il nodo in modo
univoco.
Questo per te non è applicabile perchè se si sposta il nodo è un casino :)
Però lascia perdere Parent e Child, se guardi il percorso *attuale* del nodo
puoi salvare quello.
Comunque se hai risolto, meglio.
Puoi scegliere il sistema che ritieni migliore.


 *attuale* del nodo puoi salvare quello.
Appunto. Ora cerco di spiegarmi:
Se ho la sequenza (costruita in fase di composizione del tv):
Padre
+Figlio 1
+Figlio 2
e, agendo sul tv a video, la modifico in
Padre
+Figlio 2
+Figlio 1
Io avevo la necessità di trovare (per registrarla) la nuova sequenza Padre,
Figlio 2, Figlio 1. In tal senso il percorso non mi serve (non mi aiuta).

 +Figlio 1
Ah!
Adesso ho capito :)
Tu per cambiare posizione non intendi all'interno dell'albero, ma
all'interno della sequenza del nodo padre.
Dato che per fare uno spostamento del genere immagino che tu rimuova Figlio
1 (quello che sposti) e lo reinserisci come indice 2, potresti salvarti come
chiave del nodo il FullPath e al posto dell'ultimo pezzo metterci la
posizione, cioč potresti salvare qualcosa del tipo:
' Nome, posizione, percorso completo del nodo superiore
Figlio 1, 1, Padre
Figlio 2, 2, Padre


 analizzando lo stesso, come segue (tv è il controllo TreeView):
lupo ho letto in ritardo la mail , cmq io in un prg per salvare i
cambiamenti alla stuttura scrivevo su un file, diciamo che utilizzavo la
.key com identificatore, diciamo che e' come la tua var globale mista in cui
salvi tutto, la mia key e' del tipo pare-figlio1-figlio2...|dati o note
quindi avevi un file con scritto es:
01|Root
01-01|Figlio1 in prima posizione
01-02|Figlio2 in seconda posizione
Certo il vettore e' + veloce da analizzare cmq se ti serve poi salvare
questa struttura puoi considerare questo utilizzo.
addirittura in certe condizioni salvavo tutto su file con 2 sub che ti
allego  (non ottimizzate e' per un prg personale quindi tutto arrabattato
^_^ )
In pratica cosa faccio?
Salvo nel file per prima i padri e poi metto i figli coi sottofilgi (la
struttura era solo di 3° livello Root|1|2|3) cosi mentre leggo il file
popolo la key in base a cosa sia (padre, figlio 1 o figlio 2 ) cosi con un
semplice index sai "chi" appartiene a "chi" e con l'indice riesci a ricreare
al volo la struttura, vedi se ti puo' essere utile come spunto.
'--------------------------
Private Sub SalvaAlbero()
    Dim i, Temp, cont, Gruppo, Nome, numero
On Error GoTo salto1
Open VB.App.Path & "\dati.dat" For Output As #1
cont = 1
For i = 1 To TreeView1.Nodes.Count
    If Left$(TreeView1.Nodes(i).Key, 1) = "G" Then
        Print #1, TreeView1.Nodes(i).Text
        cont = cont + 1
    End If
Next i
For i = cont To 9
    Print #1, "*"
Next i
For i = 1 To TreeView1.Nodes.Count
    Select Case Left$(TreeView1.Nodes(i).Key, 1)
        Case Is = "K"
            Gruppo = Right$(TreeView1.Nodes(i).Parent.Key, 1)
            Nome = TreeView1.Nodes(i).Text
            numero = TreeView1.Nodes(i + 1).Text
            Print #1, Gruppo & "|" & Nome & "|" & numero
        Case Else
            'vai avanti
    End Select
Next i
salto1:
    Close #1
    cmdSalva.Enabled = False
End Sub
'--------------------------
Private Sub LeggiAlbero()
    Dim Obj As Object
    Dim Temp, i, Linea
    On Error GoTo salto1
    TreeView1.Nodes.Clear
    frmMain.cmbGruppo.Clear
    Open VB.App.Path & "\dati.dat" For Input As #1
       'Leggo i gruppi
            For i = 1 To 9'<--- e' pensato per massimo 9 gruppi
                Line Input #1, Temp
                If Temp <> "*" Then
                    Set Obj = TreeView1.Nodes.Add(, , "G" & i, Temp)
                    Obj.Image = 4
                    Obj.ExpandedImage = 3
                    frmMain.cmbGruppo.AddItem Temp
                End If
            Next i
         Linea = 0
        Do Until EOF(1) = True
            Line Input #1, Temp
            Temp = Split(Temp, "|")
            Linea = Linea + 1
            'leggo il nome
                Set Obj = TreeView1.Nodes.Add("G" & Temp(0), tvwChild, "K" &
Linea, Temp(1))
                Obj.ExpandedImage = 2
                Obj.Image = 1
            'leggo il numero
                Set Obj = TreeView1.Nodes.Add("K" & Linea, tvwChild, "N" &
Linea, Temp(2))
                Obj.ExpandedImage = 2
                Obj.Image = 5
        Loop
salto1:
    frmMain.cmbGruppo.Text = frmMain.cmbGruppo.List(Val(s_Gruppo))
    Close #1
    TreeView1.Refresh
End Sub
'--------------------------
il tutto genera un file tipo :
Gruppo1
Gruppo 3
Gruppo2
*
*
*
*
*
*
2|plutyo|39300000000
3|pippo|39300000000
3|Paperino|39300000000
3|Gigio|39300000000
1|Lupo|39300000000
1|Gatto|39300000000
1|Cane|39300000000
1|Pesce|39300000000
1|NeCarneNePesce|39300000000
-- 
<Gigio2K>
Sito Comune
Nokia -> I.T.H.N. -> 
http://www.ithn.it/
VB -> I.C.L.VB -> 
http://www.it-lang-vb.net/

 01-02|Figlio2 in seconda posizione
Mi fermo qui: Come rilevi le posizioni fisiche/grafiche? Nel mio esempio ho
spostato figlio 1 dopo figlio 2, quindi devo rilevare prima figlio 2 e poi
figlio 1. Come dicevo a Zanna, il percorso completo poco m'aiuta, perchč
quando ricostruisco (dal file salvato) metterei figlio 1 prima di figlio
2...

 2...
allora guarda l'accozzaglia di codice dell'esempio di sopra. in pratica e'
tutto legato al file e alla sua prima lettura,
io uso il campo Key , G1 significa che e' il Gruppo1 , tu lo sposti e salvi
? e io ti salvo in G1 in G2 perche' mentre leggo l'albero G2 viene trovato
prima di G1 capi' ? Riguarda il codice del post precedente, li le key sono
diverse e anche il file :
'-------------------------------------------
   'Leggo i gruppi
            For i = 1 To 9'<--- e' pensato per massimo 9 gruppi
                Line Input #1, Temp
                If Temp <> "*" Then
                    Set Obj = TreeView1.Nodes.Add(, , "G" & i, Temp)
                    Obj.Image = 4
                    Obj.ExpandedImage = 3
                    frmMain.cmbGruppo.AddItem Temp
                End If
            Next i
'-------------------------------------------
Vedi quella G ? da li setto i parent alti
'-------------------------------------------
        Do Until EOF(1) = True
            Line Input #1, Temp
            Temp = Split(Temp, "|")
            Linea = Linea + 1
            'leggo il nome
                Set Obj = TreeView1.Nodes.Add("G" & Temp(0), tvwChild, "K" &
Linea, Temp(1))
                Obj.ExpandedImage = 2
                Obj.Image = 1
            'leggo il numero
                Set Obj = TreeView1.Nodes.Add("K" & Linea, tvwChild, "N" &
Linea, Temp(2))
                Obj.ExpandedImage = 2
                Obj.Image = 5
        Loop
'-------------------------------------------
Qui con Key e Relationship settto tutto, in questo caso e' un albero cosi :
+G1
    +-K1
        +-N1
    +-K2
        +-N2
+G2
    +-K1
        +-N1
tu sposti e quando salvi la struttura hai :
'-------------------------------------------
' SCRIVI nelel prime 10righe del file i nomi dei Gruppi e le posizioni
cont = 1
For i = 1 To TreeView1.Nodes.Count
    If Left$(TreeView1.Nodes(i).Key, 1) = "G" Then
        Print #1, TreeView1.Nodes(i).Text 'Qui scrive secondo l'ordine a
video i gruppi
        cont = cont + 1
    End If
Next i
'qui accodo i figli
For i = 1 To TreeView1.Nodes.Count
    Select Case Left$(TreeView1.Nodes(i).Key, 1)
        Case Is = "K" 'Se e' K e' un figlio di secondo livello a cui accodo
i sottofigli
            Gruppo = Right$(TreeView1.Nodes(i).Parent.Key, 1)
            Nome = TreeView1.Nodes(i).Text 'Figlio1
            numero = TreeView1.Nodes(i + 1).Text 'figlio2
            Print #1, Gruppo & "|" & Nome & "|" & numero
        Case Else
            'vai avanti
    End Select
Next i
'.................
diciamo che e' un caso abbastanza estremo ma guarda , io amo i campi Key e
Tag, opportunamente codificati ci fai di tutto !
-- 
-Gigio@Work(?)-