Ich habe hier jetzt schon mehrfach gelesen, dass jemand die Ordner auf seiner Festplatte in einem TreeView anzeigen lassen will, ungefähr so wie im Windows-Explorer. Hier möchte ich nun eine objektorientierte, einfache und performante Möglichkeit vorstellen, so etwas zu realisieren.
Es gibt in diesem Forum bereits Anleitungen zum rekursiven Auflisten aller Ordner innerhalb eines Ordners, jedoch sind diese Codes für unser Vorhaben nicht geeignet, da sie die gesamte Festplatte auf einem auslesen würden. Dies wollen wir aber nicht, da wir sonst Stunden vor dem ladenden TreeView sitzen würden.
Stattdessen laden wir immer nur das, was auch tatsächlich angezeigt wird. Dies habe ich gelöst, indem ich von TreeNode geerbt habe und in dieser neuen Klasse beim Expanden automatisch alle Unterordner lade.
Spoiler anzeigen
Wir haben hier zwei Arten von Knoten, einmal den normalen Ordnerknoten und einmal den Laufwerkknoten. Letztere werden vom TreeView selbst erstellt und stellen den Anfang des Baumes dar.
Beide Knoten erben von der selben Basisklasse, damit sie von dem TreeView einheitlich behandelt werden können. Das TreeView macht den ausgewählten Ordner nach außen hin mit der Eigenschaft "SelectedDirectory" verfügbar, der Aufrufer kommt mit den einzelnen Knoten nicht in Kontakt.
Geladen wird die Ordnerstruktur mit einem Aufruf von "LoadFilesystem()". Dies musste ich leider in eine extra Methode verschieben, da es im Konstruktor Komplikationen mit dem Designer gab, welcher die Knoten manuell hinzufügte.
Im Anhang findet ihr auch noch ein kleines Beispielprojekt, in dem ich auf Basis dieses Controls einen kleinen Explorer entworfen habe. Dank dieses Controls und DataBinding reduziert sich der Code in der Form auf effektiv 3 Zeilen.
Es gibt in diesem Forum bereits Anleitungen zum rekursiven Auflisten aller Ordner innerhalb eines Ordners, jedoch sind diese Codes für unser Vorhaben nicht geeignet, da sie die gesamte Festplatte auf einem auslesen würden. Dies wollen wir aber nicht, da wir sonst Stunden vor dem ladenden TreeView sitzen würden.
Stattdessen laden wir immer nur das, was auch tatsächlich angezeigt wird. Dies habe ich gelöst, indem ich von TreeNode geerbt habe und in dieser neuen Klasse beim Expanden automatisch alle Unterordner lade.
VB.NET-Quellcode
- Imports System.IO
- Public Class ExplorerTreeView : Inherits TreeView
- Public ReadOnly Property SelectedDirectory As DirectoryInfo
- Get
- If SelectedNode Is Nothing Then Return Nothing
- Return DirectCast(SelectedNode, ExplorerTreeNode).GetDirectory()
- End Get
- End Property
- Public Sub LoadFilesystem()
- For Each drive In DriveInfo.GetDrives()
- Nodes.Add(New DriveTreeNode(drive))
- Next
- End Sub
- Private MustInherit Class ExplorerTreeNode : Inherits TreeNode
- Private expanded As Boolean = False
- Friend Sub OnExpand()
- If Not expanded Then GenerateSubNodes()
- expanded = True
- End Sub
- Protected MustOverride Sub GenerateSubNodes()
- Friend MustOverride Function GetDirectory() As DirectoryInfo
- End Class
- Private Class DriveTreeNode : Inherits ExplorerTreeNode
- Private drive As DriveInfo
- Sub New(drive As DriveInfo)
- Me.drive = drive
- If drive.IsReady Then
- Text = String.Concat(drive.Name.Substring(0, 2), " ", drive.VolumeLabel)
- Nodes.Add("")
- Else
- Text = String.Concat(drive.Name.Substring(0, 2))
- End If
- End Sub
- Protected Overrides Sub GenerateSubNodes()
- Nodes.Clear()
- If drive.IsReady Then
- For Each dir In drive.RootDirectory.EnumerateDirectories()
- Try
- Nodes.Add(New DirectoryTreeNode(dir))
- Catch ex As UnauthorizedAccessException : End Try
- Next
- End If
- End Sub
- Friend Overrides Function GetDirectory() As DirectoryInfo
- If drive.IsReady Then Return drive.RootDirectory
- Return Nothing
- End Function
- End Class
- Private Class DirectoryTreeNode : Inherits ExplorerTreeNode
- Private dir As DirectoryInfo
- Sub New(dir As DirectoryInfo)
- Me.dir = dir
- Text = dir.Name
- Nodes.Add("")
- End Sub
- Protected Overrides Sub GenerateSubNodes()
- Nodes.Clear()
- For Each d In dir.EnumerateDirectories()
- Try
- Nodes.Add(New DirectoryTreeNode(d))
- Catch ex As UnauthorizedAccessException : End Try
- Next
- End Sub
- Friend Overrides Function GetDirectory() As DirectoryInfo
- Return dir
- End Function
- End Class
- Private Sub ExplorerTreeView_BeforeExpand(sender As Object, e As TreeViewCancelEventArgs) Handles Me.BeforeExpand
- DirectCast(e.Node, ExplorerTreeNode).OnExpand()
- End Sub
- End Class
Wir haben hier zwei Arten von Knoten, einmal den normalen Ordnerknoten und einmal den Laufwerkknoten. Letztere werden vom TreeView selbst erstellt und stellen den Anfang des Baumes dar.
Beide Knoten erben von der selben Basisklasse, damit sie von dem TreeView einheitlich behandelt werden können. Das TreeView macht den ausgewählten Ordner nach außen hin mit der Eigenschaft "SelectedDirectory" verfügbar, der Aufrufer kommt mit den einzelnen Knoten nicht in Kontakt.
Geladen wird die Ordnerstruktur mit einem Aufruf von "LoadFilesystem()". Dies musste ich leider in eine extra Methode verschieben, da es im Konstruktor Komplikationen mit dem Designer gab, welcher die Knoten manuell hinzufügte.
Im Anhang findet ihr auch noch ein kleines Beispielprojekt, in dem ich auf Basis dieses Controls einen kleinen Explorer entworfen habe. Dank dieses Controls und DataBinding reduziert sich der Code in der Form auf effektiv 3 Zeilen.