adszone.org
venerdì 20 settembre 2024
"Il modo corretto di pensare il software"
home
consulenza  vb.net  contatti 
  Visual Basic .NET
  TreeView
Domande

Il controllo TreeView

Il controllo TreeView visualizza informazioni all'interno di una struttura ad albero. Ogni elemento e' detto nodo dell'albero. Ogni nodo puo' contenere altri nodi. Il controllo si basa sulla collection Nodes, i cui elementi appartengono al tipo TreeNode. Operativamente, scegliamo un nodo esistente e vi inseriamo un TreeNode, dopo averlo precedentemente creato. A ciascun elemento della TreeView possiamo associare un'icona. Per introdurre le icone ci avvaliamo della proprieta': ImageList. In questa lista, le immagini sono ordinate per indice. Quando vogliamo assegnare un'immagine, lo facciamo impostando una delle due proprieta' ImageIndex, SelectedImageIndex del nodo, con l'indice dell'immagine voluta.

Presentiamo un esempio dove il TreeView e' impiegato per realizzare un Folder Browser. Ogni nodo rappresenta una directory. Marchiamo con un "+" quelle directory che ne contengono delle altre. Una ComboBox ci permette di cambiare Drive, ma non gestiamo gli errori su un'eventuale assenza di drive rimovibile.

Contolli utilizzati nel Form:

  • ComboBox - Name = ComboBox1
  • TreeView - Name = TreeView1

1) ExtractIconEx e' un'api di Windows che importiamo per estrarre le icone che assoceremo ai nodi dell'albero. Images e' la lista di immagini che estrarremo. ExtractFolderIcons e' la procedura che estrae effettivamente le icone. Tali icone si trovano nella dll di systema Shell32.

Imports System.IO

    ...
    
    Public Declare Ansi Function ExtractIconEx Lib "Shell32.dll" _
    (ByVal lpszFile As String, _
    ByVal nIconIndex As Integer, ByVal phIconLarge As IntPtr(), _
    ByVal phIconSmall As IntPtr(), ByVal nIcons As Integer) _
    As Integer

    Dim Images As ImageList

    Private Sub ExtractFolderIcons()
        Images = New ImageList()
        Dim shell32_path As String = Environment.SystemDirectory
        Dim SmallIcons(2) As IntPtr
        Dim icn As Icon
        Dim n As Integer

		' 3 - icona "Cartella chiusa", 4 - icona "Cartella aperta"
        n = ExtractIconEx(shell32_path & "\shell32.dll", 3, _
                        Nothing, SmallIcons, 2)

        icn = Icon.FromHandle(SmallIcons(0))
        Images.Images.Add(icn)

        icn = Icon.FromHandle(SmallIcons(1))
        Images.Images.Add(icn)

		' 8 - icona drive
        n = ExtractIconEx(shell32_path & "\shell32.dll", 8, _
                        Nothing, SmallIcons, 1)

        icn = Icon.FromHandle(SmallIcons(0))
        Images.Images.Add(icn)

    End Sub
        		
    Private Sub Form1_Load(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        ExtractFolderIcons()
        SetDrives()
    End Sub

2) La seguente procedura carica la ComboBox con la lista di Drive disponibili. Quindi sceglie il drive corrente e lo imposta come default. Infine popola l'albero al primo livello, dovrebbe mostrare soltanto il drive.

    Private Sub SetDrives()
        Dim drives() As String = Directory.GetLogicalDrives
        Dim i As Integer

        ComboBox1.Items.Clear()
        ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList

        For i = 0 To drives.Length - 1
            ComboBox1.Items.Add(drives(i))
        Next

        i = ComboBox1.FindStringExact(Directory.GetDirectoryRoot( _
                Directory.GetCurrentDirectory))
        ComboBox1.SelectedIndex = i

        RecreateTree(ComboBox1.Text)
    End Sub

3) Cancella tutti i nodi con il metodo Clear sulla collection Nodes. Aggiunge il nodo root con Add e chiama AddChildren per aggiungere tutte le directory contenute nel nodo root. Notate che, al nodo appena creato, assegnamo l'immagine il cui indice e' 2: (icona del drive) ImageIndex, SelectedImageIndex. Forniamo la lista di immagini attraverso la proprieta' ImageList.

    Private Sub RecreateTree(ByVal drive As String)
        TreeView1.Nodes.Clear()
        TreeView1.ImageList = Images
        Dim node As TreeNode = TreeView1.Nodes.Add(drive)
        AddChildren(drive, node)
        node.ImageIndex = 2
        node.SelectedImageIndex = 2
    End Sub

4) Estrae tutti le sottodirectory della directory fornita dal percorso sPath. E le aggiunge al nodo n. Ogni nodo ha la sua collection Nodes alla quale e' possibile aggiungere altri nodi con il metodo Add.

    Private Sub AddChildren(ByVal sPath As String, ByRef n As TreeNode)
        Dim files() As String
        Try
            files = Directory.GetDirectories(sPath)
        Catch e As Exception
            Return
        End Try
        Dim i As Integer
        For i = 0 To files.Length - 1
            n.Nodes.Add(Path.GetFileName(files(i)))
        Next
    End Sub

5) Questo evento scatta quando l'utente seleziona un nuovo drive nella ComboBox. Ci limitiamo a ricreare l'albero in base al drive scelto.

    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        RecreateTree(ComboBox1.Text)
    End Sub

6) Questa routine e' fondamentale. Si aggancia all'evento BeforeExpand del TreeView. L'evento e' generato prima che un nodo venga espanso, dopo il click dell'utente. A ciascun nodo contenuto che andremo a visualizzare, dobbiamo aggiungere i nodi che conterra', in modo che il controllo possa visualizzare il "+" di espansione. Prima di aggiungere i nodi, bisogna eliminare eventuali nodi presenti, per evitare di duplicarli visititando piu' volte lo stesso nodo. La tecnica di aggiungere ad ogni vistita, si rende necessaria per non dover creare tutto l'albero di un'intera partizione!! Notate la proprieta' FullPath che ci da' l'intero percorso che dalla radice porta al nodo interessato. Quando la directory viene espansa, bisogna cambiare la sua icona in modo che mostri l'icona aperta: con l'indice 1, impostiamo tale icona.

    Private Sub TreeView1_BeforeExpand(ByVal sender As Object, _
            ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) _
            Handles TreeView1.BeforeExpand
        Dim n As TreeNode
        For Each n In e.Node.Nodes
            n.Nodes.Clear()
            AddChildren(n.FullPath, n)
        Next
        
        If Not e.Node.Parent Is Nothing Then
            e.Node.ImageIndex = 1
            e.Node.SelectedImageIndex = 1
        End If
        
    End Sub

7) Quest'evento e' generato quando un nodo viene chiuso. In tal caso dobbiamo far disegnare l'icona di folder chiusa, il cui indice e' 0.

    
    Private Sub TreeView1_AfterCollapse(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.TreeViewEventArgs) _
                Handles TreeView1.AfterCollapse
        If Not e.Node.Parent Is Nothing Then
            e.Node.ImageIndex = 0
            e.Node.SelectedImageIndex = 0
        End If
    End Sub
    
Ultimo aggiornamento 13/01/2004