Teil 4 - Das Node-Objekt

Ausgabe 02/2001

Download Beispieldatei

In diesem Teil der Artikelfolge befassen wir uns ausschließlich mit den Eigen-schaften der Nodes-Auflistung bzw. des Node-Objektes. Da es den Rahmen des Artikels sprengen würde, umfassend auf alle Eigenschaften mit einem separaten Beispiel einzugehen,  beschränken wir uns auf zwei ausgesuchte Beispiele.

Nodes-Auflistung und Node-Objekt

Der Aufbau eines TreeView-Steuerelementes ist mit dem Aufbau eines Formulars zu vergleichen. Ein Formular ist ein Objekt mit Eigenschaften und Methoden. Es fungiert aber auch als Container für weitere Objekte, die Steuer-elemente. Genau genommen ist das Formular auch ein Steuerelement, nur eben ein sehr großes. Der Unterschied zum TreeView liegt darin, dass der „Container“ des TreeViews keine Entwurfansicht hat, sondern zur Laufzeit gefüllt werden muss; man könnte sagen, der Container ist nur virtuell. Beim TreeView wird dieser Container durch die Nodes-Eigenschaft repräsentiert. Die Nodes-Eigenschaft enthält alle Informationen zu den einzelnen Elementen, die zur Laufzeit im TreeView sichtbar sind: die Node-Objekte. Diese Auflistung von Node-Objekten ist ihrerseits wieder ein Objekt, ein sogenanntes Collection-Objekt, eben wegen seiner Con¬tai¬ner¬funktion und hat demzufolge eigene Eigenschaften und Methoden.

Im Verständnis des Unterschiedes zwischen der Nodes-Auflistung und dem Node-Objekt liegt der Schlüssel für die Arbeit mit dem TreeView. Wann muss man die Nodes-Auflistung und wann ein Node-Objekt referenzieren? Vielen Access-Anwendern ist der objektorientierte Ansatz nicht so geläufig und deshalb fällt der Einstieg in die Programmierung mit dem Strukturansicht-Steuerelemente relativ schwer. Das Sammelsurium an Informa¬tions¬bruchstücken in der Onlinehilfe macht es leider auch nicht einfacher.

Dabei muss man sich nur folgende Frage stellen: soll sich die Eigenschaft oder Methode auf die gesamte Auflistung (Nodes) oder ein einzelnes Element (Node) der Liste beziehen? Zugegeben, es gibt einige Grenzfälle wo beides denkbar ist. In Tabelle 1 erfahren Sie mehr über das Logikmodell der Methoden.

Der Schritt von der Nodes-Auflistung zum Node-Objekt ist nur minimal. Mit der Syntax Forms![FormularName]![TreeviewName].Nodes  verweisen Sie auf die komplette Auflistung von Node-Objekten. Mit Hilfe der Item-Methode, und einem gültigen Index bzw. Key im Parameter, erhalten Sie eine Referenz auf ein einzelnes Element in der Auflistung zurück:

Forms![FormularName]![TreeviewName].Nodes.Item(1)

Da die Item-Methode die Standardmethode der Node-Auflistung darstellt, kann Sie auch weggelassen werden:

Forms![....].Nodes(1)

Tabelle 1: Methoden der Nodes-Auflistung bzw. des Node-Objektes

Methode

Bezug

Logik

Add

Nodes

Syntax: TreeView-Objekt.Nodes.Add [weitere Parameter]

Der Auflistung wird ein neuer Eintrag hinzugefügt. Durch optionale Parametern werden weitere Angaben zum neuen Node übergeben (siehe Teil 1 der Artikelfolge).

Item

Nodes

Syntax: TreeView-Objekt.Nodes.Item [Node-ID/-Key]

Gibt die Referenz auf das im Parameter mit ID oder Key angegebene Node-Objekt der Nodes-Auflistung zurück. Die Referenz kann auf eine Objekt-Variable gespeichert werden und ist vom Typ Node. Mit dieser Variable können alle Eigenschaften des Node-Objekt abgefragt bzw. gesetzt werden (Tabelle 2).

Clear

Nodes

Syntax: TreeView-Objekt.Nodes.Clear

Der Inhalt der Auflistung wird komplett gelöscht.

Remove

Nodes

Syntax: TreeView-Objekt.Nodes.Remove [Node-ID/-Key]

Ein einzelner Knoten (Node) soll aus der Auflistung entfernt werden. Die Remove-Methode stellt einen Grenzfall dar: man könnte auch das Node-Objekt referenzieren und dann löschen. Allerdings würde man sich den Boden unter den Füssen wegziehen, soll heißen, Sie stellen sich ja auch nicht auf einen Holzfußboden und schneiden um Ihre Füße herum ein kreisrundes Stück aus dem Boden. Dann würden Sie in den Keller fallen. Genauso verhält es sich auch mit der Remove-Methode. Im Paramter wird der Index oder Key des Nodes übergeben, welches gelöscht werden soll.

EnsureVisible

Node

Syntax: TreeView-Objekt.Nodes(ID/Key).EnsureVisible

Ein bestimmter Knoten soll im TreeView sichtbar sein, dazu werden, wenn nötig, automatisch Knoten aufgeklappt und Bildläufe durchgeführt.

Eigenschaften des Node-Objekts bzw. der Nodes-Auflistung

In Tabelle 1 sehen Sie, dass sich die meisten Methoden auf die Nodes-Auflistung beziehen. Bei den Eigenschaften verhält es sich genau umgekehrt, Sie beziehen sich fast alle auf das einzelne Node-Objekt. Die Tabelle 2 gibt Ihnen einen Überblick über die meisten Eigenschaften für ein Node-Objekt.

Eine Ausnahme bei den Eigenschaften bildet die Count-Eigenschaft. Mit Count ermitteln Sie die Anzahl der Einträge in der Nodes-Auflistung:

Syntax: Forms![FormularName]![TreeviewName].Nodes.Count

Ebenso fallen folgenden Eigenschaften aus dem Rahmen:

Jede dieser Eigenschaften gibt einen Verweis, relativ zum referenzierten Knoten, auf ein bestehendes Node-Objekt zurück (siehe Tabelle 2). Der Rückgabewert kann mit Hilfe der Set-Methode auf eine Objekt-Variable gespeichert werden. Das folgende Codebeispiel gibt einen Verweis auf das erste untergeordnete Node-Objekt zurück, relativ zum Knoten mit dem Key “A1“, und speichert den Rückgabewert in die Objekt-Variable ndX:

Dim ndX As Node
Set ndX = Forms![frm_Beispiel]![Treeview].Nodes.Item(“A1“)
Set ndX = ndX.Child
MsgBox ndX.Key & “ – “ ndX.Text

Die Objekt-Variable ndX kann nun als ganz normales Node-Objekt weiter-verwendet werden und besitzt demzufolge alle Eigenschaften und Methoden eines herkömmlichen Node-Objektes, z.B. die Key-, Text oder Parent-Eigenschaft.

Sie können die Eigenschaften aber auch gleich hintereinander hängen, was die Lesbarkeit des Codes in den meisten Fällen nicht gerade steigert:

MsgBox Forms![frm_Beispiel]![Treeview].Nodes.Item(“A1“).Child.Key

Bitte beachten Sie, dass ein Verweis nur zurückgegeben werden kann, wenn ein solches Node-Objekt überhaupt vorhanden ist. Hat der Knoten in unserem Beispiel keine untergeordneten Elemente, tritt der Fehler mit der Nummer 91 auf. Das gleiche passiert, wenn der mit Key “A1“ referenzierte Knoten gar nicht existiert.

Tabelle 2: Eigenschaften des Node-Objektes

Eigenschaft

Beschreibung

Children

Der Rückgabewert ungleich 0 gibt an, dass der Knoten untergeordnete Einträge hat. Die Rückgabe entspricht also der genauen Anzahl.

Expanded

Gibt an oder legt fest, ob der Knoten aufgeklappt ist (Ja/Nein).

Eigenschaft kann gelesen und geschrieben werden.

Selected

Gibt an oder legt fest, ob der Knoten gerade ausgewählt ist (Ja/Nein). Eigenschaft kann gelesen und geschrieben werden.

Sorted

Gibt an oder legt fest, ob die untergeordneten Einträge des referenzierten Knotens alphabetisch sortiert werden sollen (Ja/Nein). Schreib-lese-Zugriff.

Image

SelectedImage

ExpandedImage

Dem Knoten können jeweils bis zu drei kleine Symbole zugeordnet werden, die drei unterschiedliche Zustände des Knotens visualisieren: wenn der Knoten markiert ist (SelectedImage), wenn der Knoten aufgeklappt ist (ExpandedImage) oder keines von beiden (Image). Wenn nur die Image-Eigenschaft gesetzt wird, wird das Symbol auch für die beiden anderen Zustände angezeigt. Um diese Eigenschaft setzen zu können muss allerdings ein ImageList-Steuerelement vorhanden sein (wird in der nächsten Ausgabe behandelt).

Tag

In der Tag-Eigenschaft können zusätzliche Informationen in Textform gespeichert werden, die im Treeview nicht angezeigt werden.

Text

Diese Eigenschaft enthält den Knotentext, der im TreeView angezeigt wird.

Fullpath

Gibt den kompletten Pfad des Knoten im TreeView zurück.
Die einzelnen Ebenen werden durch ein beliebiges Zeichen getrennt dargestellt. Dieses Zeichen kann durch die Indentation-Eigenschaft des TreeView-Objektes (auch zur Laufzeit) eingestellt werden. Eigenschaft kann nur gelesen werden.

Root

Objekt-Verweis auf das übergeordnete Node der obersten Ebene.

Parent

Objekt-Verweis auf das direkt übergeordnete Node.

Child

Objekt-Verweis auf das direkt untergeordnete Node.

Next

Objekt-Verweis auf das nächste gleichgeordnete Node.

Previous

Objekt-Verweis auf das vorherige gleichgeordnete Node.

LastSibling

Objekt-Verweis auf das letzte gleichgeordnete Node.

FirstSibling

Objekt-Verweis auf das erste gleichgeordnete Node.

Index, Key

Eigenschaften, die das Node-Objekt in der Nodes-Auflistung eindeutig identifizieren.

Suchen im TreeView

Folgendes Beispiel soll den Umfang mit der Nodes-Auflistung demonstrieren. Wenn Sie einen Eintrag im TreeView automatisch suchen lassen wollen, müssen Sie die Text-Eigenschaften der einzelnen Node-Objekte im Collection-Objekt (Nodes-Auflistung) durchsuchen. Die Suche besteht in unserem Beispiel (Listing 1) aus zwei Teilen: zum Einen aus der Eingabe des Suchbegriff (Prozedur beim Klick auf eine Schaltfläche) und zum Anderen aus dem eigentlichen Suchalgorithmus, welche als nichtöffentliche Funktion ebenfalls im Klassenmodul des Formulars gespeichert wird (Private Function Search_Node). Die Suchfunktion muss sich wegen einer bestimmten Codezeile lokal im Formularmodul befinden

Call TreeView_NodeClick(TreeView.Nodes(item.Key))

Der Aufruf des NodeClick-Ereignisses ist in unserem Beispiel sehr wichtig, damit der gefundene Eintrag nicht nur im TreeView markiert, sondern auch der entsprechende Datensatz im Formular angezeigt wird. Außerdem könnte es sein, dass weitere Aktionen mit einem NodeClick-Ereignis einhergehen, die andernfalls übergangen würden.

Abbildung 1: Eintrag im TreeView suchen

Abbildung 1: Eintrag im TreeView suchen

Die „relative“ Umgebung eines Knotens?

Unser zweites Beispiel (Listing 2) soll die Anwendung der Count-Eigenschaft und den „Umgebungs-Eigenschaften“ erläutern. Außerdem zeigt der Code nochmals den Umgang mit einer Objekt-Variablen, die den Code schlank und vor allem leicht lesbar macht. Auch hier ist der Code wieder in zwei Teile geteilt:

Der erste Teil des Codes besteht aus einer Ereignis-Prozedur, die überprüft, ob die Bedingungen zur Anzeige der Knoten-Eigenschaften korrekt sind. In unserem Beispiel soll der Informationstext mit Hilfe einer MessageBox dann angezeigt werden, wenn mit der rechten Maustaste auf einen Knoten geklickt wurde. Zu diesem Zweck verwenden wir das TreeView-Ereignis MouseUp.

Über den Parameter Button kann  geprüft werden, ob auch wirklich die rechte Maus­taste gedrückt wurde. Die Werte, welche die einzelnen Parameter dabei annehmen können, kann man im Objektkatalog von Access unter Constants nachschlagen, oder  in der Online-Hilfe.

Erst jetzt wird im zweiten Teil, in einer globalen Funktion, der Meldungstext generiert und angezeigt. Der Fehler 91 wird dabei sofort berücksichtigt, um eine umständliche Fehlerbehandlungsroutine zu umgehen. Durch die Übergabe des TreeView-Objektes im Parameter ist die Funktion universal einsetzbar.

Die Beispiele und der bisherige Code können auf der Homepage www.mwelling.de herunter­geladen werden.

Abbildung 2: Die Umgebung eines Knotens anzeigen

Abbildung 2: Die Umgebung eines Knotens anzeigen

Ereigniss-Parameter des TreeView

Im Eigenschaftsfenster eines TreeView werden nur 5 Ereignisse angezeigt, obwohl das Steuerelement viel mehr Ereignisse beinhaltet. In der Onlinehilfe sind weitere aber noch längst nicht alle Ereignisse zum TreeView aufgelistet. Außerdem haben einige Ereignisse sehr viele Parameter, die man umständlich abschreiben müsste. Es gibt aber noch einen schnelleren Weg. Im Modulfenster des Formulars wird eine Menüleiste mit zwei Kom­binations­feldern angezeigt. Im rechten Kombinationsfeld sind alle Steuerelemente des betreffenden Formulars, alphabetisch nach Namen sortiert, aufgelistet. Im linken Kombinationsfeld befindet sich eine List mit unterstützten Ereignissen. Wenn Sie nun im rechten Dropdown-Feld eine Steuerelement auswählen, bekommen Sie im Linken alle dazugehörigen und vor allem verfügbaren Ereignisse angezeigt. Verfügbar soll heißen, dass einigen Onlinehilfen auch Ereignisse, Eigenschaften und Methoden beschreiben, die in Access nicht unterstützt werden. Wenn Sie nun ein Eintrag im Linken Dropdown-Feld auswählen, wird die Ereignis-Prozedur automatisch in das Klassenmodul des Formulars eingefügt, und zwar mit korrekter Syntax und allen Parametern.

 

Abbildung 3: automatisch Ereignisprozeduren im Klassenmodul erzeugen

 Abbildung 3: automatisch Ereignisprozeduren im Klassenmodul erzeugen

Listing 1: Code zum Suchen im TreeView

Private Sub btn_Node_Search_Click()
 
   Dim tof    As Boolean   '*TrueOrFalse
   Dim ib_bck As String    '* InputBox-Rückgabe
 
   '* Inputbox anzeigen, und Eingabe zwischenspeichern.
   ib_bck = InputBox("Bitte geben Sie den Suchbegriff ein...!", _
                     "Begriff suchen")
 
   '* Wenn kein Suchbegriff eingegeben wurde, ...
   '* oder Abbruch-Schaltfläche gedrückt wurde, ...
   If ib_bck = "" Then
      '* ... dann Abbruch!
      Exit Sub
   Else
      '* ... sonst Suchealgorithmus aufrufen!
      tof = Search_Node(Me![TreeView], ib_bck)
   End If
 
   '* Wenn nichts gefunden wurde, ...
   If tof = False Then
      '* ... dann Meldung ausgeben!
      MsgBox "Es wurde kein passender Eintrag gefunden!", _
             vbInformation + vbOKOnly, _
             "nichts gefunden"
   End If
 
End Sub
 
 
'* lokale Funktion, die nach Einträgen im TreeView sucht *
'*********************************************************
Private Function Search_Node _
                (ByVal TreeView As Object, _
                 ByVal p_SearchString As String) As Boolean
 
   Dim item As Node    '* Node-Objektvariable
 
   '* Funktion initialisiren
   Search_Node = False
 
   '* Für jedes einzelne Elemente der Nodes-Auflistung! ...
   For Each item In TreeView.Nodes
 
      '* ... ist Suchbegriff in Text-Eigenschaft enthalten? ...
      If InStr(1, item, p_SearchString) Then
 
         '* JA, Suche war erfolgreich!!!
         Search_Node = True
 
         '* ... wähle gefundenes Node-Objekt aus ...
         TreeView.Nodes(item.Key).Selected = True
         '* ... und stoße NodeClick-Ereignis an.
         Call TreeView_NodeClick(TreeView.Nodes(item.Key))
 
         '* Soll weitergesucht werden?
         If MsgBox("Weitersuchen?", _
                   vbQuestion + vbYesNo + vbDefaultButton1, _
                   "Suche") = vbNo Then
            '* ... wenn nicht, dann Abbruch!
            Exit Function
         End If
        
      End If
 
   '* Nächstes Node-Objekt
   Next item
 End Function

Listing 2: Code zur „relativen“ Umgebung eines Node-Objektes
Private Sub TreeView_MouseUp(ByVal Button As Integer, _
                             ByVal Shift As Integer, _
                             ByVal x As Long, _
                             ByVal y As Long)
 
   '* Wenn rechte Maustaste gedrückt wurde, ...
   If Button = acRightButton Then
      '* ... dann Eigenschaften zum Node anzeigen.
      Call TreeView_Property(Me![TreeView])
   End If
 
End Sub
 
'* globale Funktion, die den Meldung generiert und anzeigt *
'***********************************************************
Public Function TreeView_Property _
      (ByVal TreeView As Object) As Boolean
   Dim ndX       As Node     '* Node-Objektvariable
   Dim v_NodeKey As Variant  '* Hilfs-Variablen definieren
   Dim tof       As Boolean  '* TrueOrFalse
   Dim msg_txt As String     '* MessageBox-Text
   Dim msg_ret As Long       '* MessageBox-Rückgabe
 
   '* Funktion initialisieren
   TreeView_Property = False
 
   '* Plausibilitäts-Kontrolle *
   '****************************
  
   '* Key des aktuell markierten Knoten ermitteln.
   v_NodeKey = TreeView.SelectedItem.Key
   '* Wenn kein Eintrag markiert, Abbruch
   If IsNull(v_NodeKey) Then GoTo RunError
 
   '* Node-Objektvariable initialisieren
   Set ndX = TreeView.Nodes(v_NodeKey)
 
   '* Meldungstext-Variable initialisieren
   msg_txt = ""
   '* Meldungstext generieren
   msg_txt = msg_txt & "Aktuelle Stelle: "
   msg_txt = msg_txt & ndX.Text
   msg_txt = msg_txt & Chr$(13)
   msg_txt = msg_txt & "übergeordnete Stelle: "
   '* Wenn kein übergeordneter Eintrag existiert!
   On Error Resume Next
   msg_txt = msg_txt & ndX.Parent.Text
   If Err.Number = 91 Then msg_txt = msg_txt & "{keine}"
   On Error GoTo RunError
   msg_txt = msg_txt & Chr$(13)
   msg_txt = msg_txt & "untergeordnete Stellen: "
   msg_txt = msg_txt & IIf(ndX.Children <> 0, _
       "JA (Anzahl: " & ndX.Children & ")", _
       "NEIN")
 
   '* Meldungsbox anzeigen
   MsgBox msg_txt, vbInformation + vbOKOnly, _
          "Eigenschaften der Stelle"
 
   '* Bei Erfolg, TRUE auf Funktion schreiben
   TreeView_Property = tof
 End Function