TreeView-Elemente im Griff

Das TreeView-Steuerelement ist der Platzhirsch unter den Steuerelementen zur Anzeige hierarchischer Daten. Wie man es füllt, haben wir in diversen Beiträgen gezeigt – aber wie ändert man darin enthaltene Elemente später und wie greift man überhaupt auf diese zu Dieser Beitrag beleuchtet, wie Sie beliebige Elemente referenzieren, löschen, durchlaufen, ersetzen und ihre Eigenschaften anpassen.

Wer noch keine Erfahrung mit dem TreeView-Steuerelement gesammelt hat und diesen Beitrag zum Anlass nimmt, sich einmal damit zu beschäftigen, sei auf die erwähnten bereits erschienenen Beiträge verwiesen – die Suche nach dem Begriff TreeView im Onlinearchiv von www.access-im-unternehmen.de dürfte genügend Lesematerial liefern.

An dieser Stelle wollen wir uns nur peripher mit dem dem Füllen des TreeViews beschäftigen und eher auf den Umgang mit dem bereits voller Früchte hängenden Baum konzentrieren. Da gibt es nämlich genügend Fragestellungen wie etwa die folgenden:

  • Wie referenziere ich ein Element im TreeView
  • Wie erfahre ich, wie das aktuelle Element heißt
  • Wie springe ich zum ersten, letzten, vorherigen oder nächsten Element im TreeView
  • Wie kann ich die vorhandenen Elemente durchlaufen

Beispieldatenbank

Damit Sie sich als TreeView-Neuling nicht durch alle bereits erschienenen Beiträge zu diesem Thema durchkämpfen müssen, hier in aller Kürze der Ablauf zum Füllen des TreeViews mit Beispieldaten. Die Beispieldatenbank enthält drei Tabellen namens tblA, tblB und tblC, die im Datenmodell wie in Bild 1 aussehen und bei denen die Tabelle tblB über das Fremdschlüsselfeld AID mit Tabelle tblA und die Tabelle tblC auf die gleiche Weise mit tblB verknüpft ist. Die kleine Routine aus Listing 1 füllt die Tabellen mit Beispieldaten.

Listing 1: Schreiben von Beispieldaten in die Tabellen tblA, tblB und tblC

Public Sub Beispieldaten()
Dim db As DAO.Database
Set db = CurrentDb
Dim intA As Integer, lngA As Long, intB As Integer, lngB As Long, intC As Integer
db.Execute "DELETE FROM tblA€, dbFailOnError
For intA = 1 To 5
 db.Execute "INSERT INTO tblA(AWert) VALUES(€Wert€ & intA & "€)€, dbFailOnError
    lngA = db.OpenRecordset("SELECT @@IDENTITY€).Fields(0)
    For intB = 1 To 5
        db.Execute "INSERT INTO tblB(BWert, AID) VALUES(€Wert€ & intB & "€, " & lngA & ")€, _
        dbFailOnError
        lngB = db.OpenRecordset("SELECT @@IDENTITY€).Fields(0)
        For intC = 1 To 5
            db.Execute "INSERT INTO tblC(CWert, BID) VALUES(€Wert€ & intC & "€, " _
            & lngB & ")€, dbFailOnError
        Next intC
    Next intB
Next intA
End Sub

Listing 3: Auf- und abbewegen im TreeView-Steuerelement

Testen und debuggen ohne Hindernisse

Wenn Sie die folgenden Beispiele ausprobieren oder eigene Zugriffe auf die Elemente des TreeView-Steuerelements programmieren, werden zweifelsohne Fehler auftreten. Dies führt dazu, dass weitere Aufrufe nicht mehr funktionieren, wenn Sie nicht das Formular schließen und erneut öffnen. Woran liegt das Access speichert Variablen nur so lange, bis ein Fehler auftritt. Access 2007-Entwickler können die TempVars-Auflistung verwenden, um Variablen darin zu speichern, die auch beim Auftreten von Fehlern nicht ihren Wert verlieren. Alle anderen sollten eine entsprechende Fehlerbehandlung einbauen, die unbehandelte Fehler ausschließt – behandelte Fehler löschen keine Variableninhalte. Wenn Sie zum Experimentieren oder in der Anfangsphase eines Projekts auf eine Fehlerbehandlung verzichten wollen, können Sie sich anderweitig behelfen. Vom Löschen der Variablen ist vor allem objTreeView betroffen, das nur einmal beim Laden des Formulars mit einem Verweis auf ctlTreeView.Object bestückt wird. Wenn Sie dauerhaft über diese Variable auf ctlTreeView.Object zugreifen möchten, schreiben Sie einfach folgende Zeilen in den Kopf des Klassenmoduls:

Dim WithEvents m_TreeView As MSComctlLib.TreeView
Private Function objTreeView() As
 MSComctlLib.TreeView
    If m_TreeView Is Nothing Then
        Set m_TreeView = Me.ctlTreeView.Object
    End If
    Set objTreeView = m_TreeView
End Function

Statt einer Objektvariablen namens objTreeView haben Sie es nun mit einer gleichnamigen Funktion zu tun. Der eigentliche Verweis wird in der Objektvariablen m_TreeView gespeichert. Über die Funktion objTreeView können Sie im übrigen Code genau so auf ctlTreeView.Object zugreifen wie über die zuvor definierte Variable objTreeView. Die Funktion prüft, ob m_TreeView noch einen Wert enthält, was normalerweise der Fall ist, oder ob sie leer ist – dies ist in der Regel auf einen vorherigen unbehandelten Fehler zurückzuführen – und füllt sie erneut mit einem Verweis auf ctlTreeView.Object.

Noch ein Hinweis: Wenn Sie diese Variante verwenden, müssen Sie natürlich die folgende Zeile aus dem Form_Load-Ereignis des Formulars entfernen:

Set objTreeView = Me!ctlTreeView.Object
Private Sub cmdNachOben_Click()
    If objTreeView.SelectedItem.Index > 1 Then
        objTreeView.SelectedItem = objTreeView.Nodes.Item(objTreeView.SelectedItem.Index - 1)
    Else
        objTreeView.SelectedItem = objTreeView.Nodes.Item(objTreeView.Nodes.Count)
    End If
    End Sub
Private Sub cmdNachUnten_Click()
    If objTreeView.SelectedItem.Index < objTreeView.Nodes.Count Then
        objTreeView.SelectedItem = objTreeView.Nodes.Item(objTreeView.SelectedItem.Index + 1)
    Else
        objTreeView.SelectedItem = objTreeView.Nodes.Item(1)
    End If
    End Sub

pic001.png

Bild 1: Datenmodell für das Füllen des TreeView-Steuerelements

Das Formular frmTreeView enthält ein Steuerelement namens ctlTreeView, dessen Einstellungen Sie zunächst nicht anpassen. Der Code zum Füllen und für den Zugriff auf das TreeView-Steuerelement landet im Klassenmodul des Formulars frmTreeView, das Sie durch die Auswahl des Eintrags [Ereignisprozedur] für die Eigenschaft Beim Laden des Formulars und anschließendes Anklicken der Schaltfläche mit den drei Punkten anlegen. Dort finden Sie gleich eine leere Ereignisprozedur namens Form_Load, die Sie aber noch nicht bestücken. Zuerst fügen Sie in den Kopf des Moduls die folgende Deklaration ein, die das Schreiben des Beispielcodes durch die Bereitstellung von IntelliSense vereinfacht:

Dim WithEvents objTreeView As MSComctlLib.TreeView

Dann vervollständigen Sie die Ereignisprozedur so, dass diese die erste Ebene des TreeView-Steuerelements mit den Datensätzen aus Tabelle tblA füllt (s. Listing 2). Während des Füllens ruft die Routine gleich die Routine FillNodeA und diese wiederum FillNodeB auf, um die Datensätze der Tabellen tblB und tblC ebenfalls zum TreeView hinzuzufügen. Dieses sieht nach dieser Behandlung wie in Bild 2 aus.

Listing 2: Füllen der ersten drei Ebenen des TreeViews mit den Daten der Beispieltabellen

Private Sub Form_Load()
    Dim rstA As DAO.Recordset
    Dim objNode As MSComctlLib.Node
    ...
    Set objTreeView = Me!ctlTreeView.Object
    Set rstA = db.OpenRecordset("SELECT * FROM tblA€, dbOpenDynaset)
    objTreeView.LineStyle = tvwRootLines
    Do While Not rstA.EOF
        Set objNode = objTreeView.Nodes.Add(, , "A€ & rstA!AID, rstA!AWert)
        FillNodeA objNode, rstA!AID
        rstA.MoveNext
    Loop
    ...
    End Sub
Private Sub FillNodeA(objNode As MSComctlLib.Node, lngIDA As Long)
    Dim rstB As DAO.Recordset
    ...
    Set rstB = db.OpenRecordset("SELECT * FROM tblB WHERE AID = " & lngIDA, dbOpenDynaset)
    Do While Not rstB.EOF
        Set objNode = objTreeView.Nodes.Add("A€ & lngIDA, tvwChild, "B€ & rstB!BID, rstB!BWert)
        FillNodeB objNode, rstB!BID
        rstB.MoveNext
    Loop
    ...
    End Sub
Private Sub FillNodeB(objNode As MSComctlLib.Node, lngIDB As Long)
    Dim rstC As DAO.Recordset
    ...
    Set rstC = db.OpenRecordset("SELECT * FROM tblC WHERE BID = " & lngIDB, dbOpenDynaset)
    Do While Not rstC.EOF
        Set objNode = objTreeView.Nodes.Add("B€ & lngIDB, tvwChild, "C€ & rstC!CID, rstC!CWert)
        rstC.MoveNext
    Loop
    ...
    End Sub

pic002.png

Bild 2: Das mit den Beispieldaten gefüllte TreeView-Steuerelement

TreeView-Elemente referenzieren

Die Elemente heißen nun in der ersten Ebene A1, A2, A3 …, in der zweiten Ebene B1, B2, B3… und in der dritten Ebene C1, C2, C3 und so weiter. Wenn Sie sich noch ein wenig aufwärmen möchten, legen Sie noch eine Tabelle, Beispieldaten und die FillNode…-Prozedur für eine oder mehrere weitere Ebenen an.

Schauen wir uns an, welche Möglichkeiten es gibt, die einzelnen Node-Elemente zu referenzieren. Holen wir uns zunächst einen gültigen Verweis auf das TreeView-Steuerelement selbst und testen dieses. Das erledigt die Abfrage der Name-Eigenschaft dieses Steuerelements im Direktfenster (siehe Bild 3):

pic003.png

Bild 3: Referenztest im Direktbereich

Debug.Print Forms!frmTreeView!ctlTreeView.Name

Da wir im Folgenden relativ häufig direkt auf das TreeView-Steuerelement zugreifen möchten und dabei auch IntelliSense nutzen wollen, bauen wir eine kleine Funktion, die uns einen Verweis auf das TreeView-Steuerelement liefert. Diese sieht so aus:

Dim m_TreeView As MSComctlLib.TreeView
Public Function GetTreeView() As
 MSComctlLib.TreeView
    If m_TreeView Is Nothing Then
        Set m_TreeView =
        Forms!frmTreeView!ctlTreeView.Object
    End If
    Set GetTreeView = m_TreeView
End Function

Die Funktion speichert den Verweis in einer globalen Variablen namens m_TreeView und liefert deren Inhalt als Funktionswert zurück, wenn die Variable bereits gefüllt ist. Wenn nicht, erledigt sie dies innerhalb der If…Then-Bedingung.

Im Code Ihrer Anwendung sollte das Steuerelement jedoch auf die im Klassenmodul des Formulars deklarierte Variable etwa namens objTreeView zugreifen.

Für die folgenden Beispiele gilt analog: Ersetzen Sie GetTreeView durch objTreeView, um innerhalb des Klassenformulars auf das TreeView-Objekt zuzugreifen.

GetTreeView liefert nun immer einen Verweis auf das TreeView-Objekt – vorausgesetzt, das Formular ist in der Formularansicht geöffnet.

Im Direktfenster, wo einige unserer Tests stattfinden werden, steht damit auch das gewünschte IntelliSense zur Verfügung (siehe Bild 4).

pic004.png

Bild 4: IntelliSense im Direktfenster

Die Gesamtzahl der im TreeView-Objekt enthaltenen Node-Elemente liefert dieser Ausdruck:

GetTreeView.Nodes.Count

Elemente durchlaufen

Informationen zu allen Nodes erhalten Sie über eine herkömmliche For…Next-Schleife und die Nodes-Auflistung. Die folgenden Zeilen liefern alle Key-Werte (also A1, A2 und so weiter):

Dim i As Integer
For i = 1 To GetTreeView.Nodes.Count
    Debug.Print GetTreeView.Nodes(i).Key
Next i

Dies gelingt auch über eine For Each-Schleife:

Dim objNode As MSComctlLib.Node
For Each objNode In GetTreeView.Nodes
    Debug.Print objNode.Key
Next objNode

Die Key-Eigenschaft liefert den Key-Wert, die Text-Eigenschaft den angezeigten Text eines Nodes – das sind die beiden Werte, die wir in der Routine Form_Load angelegt haben. Wenn Sie den Key-Wert eines Nodes kennen, können Sie diesen direkt referenzieren, um etwa seinen Text zu ermitteln:

Debug.Print GetTreeView.Nodes("A5").Text
Wert A5

Das geht auch noch kürzer, weil Text die Standardeigenschaft des Node-Objekts ist:

Debug.Print GetTreeView.Nodes("A5")
Wert A5

Aktuelles Element referenzieren

Wenn Sie etwas mit dem aktuell ausgewählten TreeView-Element erledigen möchten, ist das ganz einfach. Die SelectedItem-Eigenschaft des TreeView-Objekts liefert das gewünschte Element, auf das Sie auch direkt zugreifen können:

Debug.Print GetTreeView.SelectedItem
Wert A5

Ein Element zum aktuellen Element machen

Wenn Sie den Key eines Elements kennen und dieses markieren möchten, gelingt dies ebenfalls mit der SelectedItem-Eigenschaft:

GetTreeView.SelectedItem =
GetTreeView.Nodes("A2")

Das Zuweisen des Key-Werts allein reicht nicht aus – ganz im Gegenteil: Sie weisen der Text-Eigenschaft des ausgewählten Elements den angegebenen Wert zu.

Folgendes würde zur änderung des Beispiel-TreeViews aus Bild 5 führen:

pic005.png

Bild 5: änderung des Texts eines TreeView-Elements

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar