Das TreeView-Steuerelement eignet sich perfekt zur Anzeige hierarchischer Daten. Allerdings hat es einen Nachteil: Im Gegensatz zu gebundenen Formularen kann man darin nicht mal eben einen neuen Datensatz anlegen, einen Datensatz löschen oder bearbeiten. Dazu muss man Hand in Hand mit einem weiteren Element wie etwa einem Unterformular zur Anzeige des aktuellen Datensatzes arbeiten. Aber wie legt man mal eben einen neuen Datensatz von einem TreeView-Steuerelement aus an oder löscht ein Element Dies gelingt am einfachsten per Kontextmenü. Dieser Artikel liefert das nötige Know-how und einige Beispiele.
Beispieldatenbank
Die Beispiele dieses Artikels finden Sie in der Datenbank 1311_TreeView.mdb.
Beispielformular
Als Beispielformular verwenden wir das im Artikel TreeView und Unterformulare aufgebaute Formular, das wir kopiert und frmTreeViewKontextmenue genannt haben.
Damit wir über das TreeView-Steueelement leicht neue Kunden hinzufügen können, haben wir es etwas umgestaltet: Statt wie zuvor alle Kunden in der ersten Ebene des TreeView-Steuerelements anzuzeigen, haben wir einen Root-Knoten namens Kunden angelegt und alle Kunden-Elemente unterhalb dieses Knotens hinzugefügt. Dazu waren die in Listing 1 dargestellten änderungen nötig. Dort fügen wir zunächst mit der Add-Methode das Root-Element mit dem Key-Wert r0 und dem Text Kunden hinzu. Dieses wird mit Expanded = True aufgeklappt. Die beim Durchlaufen der Tabelle tblKunden hinzugefügten Elemente legt die Prozedur dann unterhalb des Elements mit dem Key-Wert r0 an. Das Ergebnis sieht schließlich wie in Bild 1 aus.
Bild 1: Hinzufügen eines Root-Knotens zum TreeView-Steuerelement
Element löschen
Als Erstes wollen wir einen Kontextmenü-Eintrag hinzufügen, mit dem der Benutzer eines der Kunden-Elemente löschen kann. Das Kontextmenü soll beim Anklicken des zu löschenden Elements angezeigt werden und einen Eintrag namens Löschen anbieten. Um das Herunterdrücken der rechtem Maustaste abzufangen, verwenden wir die Ereignisprozedur, die durch das Ereignis MouseDown ausgelöst wird. Für ActiveX-Steuerelemente legen Sie eine solche Ereignisprozedur nicht über die entsprechende Eigenschaft im Eigenschaftsfenster an, sondern direkt im VBA-Fenster.
Für das TreeView-Steuerelement liegt bereits eine Objektvariable namens m_TreeView vor, die mit dem Schlüsselwort WithEvents deklariert wurde und somit auch Ereignisprozeduren ausführt.
öffnen Sie also das Klassenmodul Form_frmTreeviewKontextmenue und wählen Sie dann erst im linken Kombinationsfeld den Eintrag m_TreeView und im rechten den Eintrag MouseDown aus (siehe Bild 2).
Bild 2: Anlegen der Ereignisprozedur MouseDown
Die auf diese Weise erstellte Ereignisprozedur m_TreeView_MouseDown liefert mit dem Parameter Button einen Wert, der über die betätigte Maustaste Auskunft gibt. Diesen können Sie über die beiden Konstanten acLeftButton oder acRightButton prüfen. In diesem Fall interessiert uns, ob der Benutzer die rechte Maustaste gedrückt hat. Wir können die Ereignisprozedur also mit einer Bedingung wie der folgenden anreichern:
Select Case Button Case acRightButton 'Kontextmenü anzeigen End Select
Fehlt nur noch der Code, der ermittelt, welches Element der Benutzer angeklickt hat und der das passende Kontextmenü zusammenstellt. Hat der Benutzer tatsächlich mit der rechten Maustaste auf das Treeview-Steuerelement geklickt, können verschiedene Fälle eintreten:
- Er hat mit einer anderen Maustaste als der rechten geklickt.
- Er hat mit der rechten Maustaste ein Element im TreeView-Steuerelement angeklickt.
- Er hat mit der rechten Maustaste auf einen leeren Bereich im TreeView-Steuerelement geklickt.
Wenn der Benutzer kein Element getroffen hat, soll nichts geschehen. Aber wie prüfen wir das Indem wir die Funktion HitTest des TreeView-Steuerelements nutzen. Diese erwartet die Koordinaten für den Punkt, den der Benutzer angeklickt hat. Diese liefert die Ereignisprozedur MouseDown ebenfalls, und zwar mit den Parametern x und y.
Da wir Informationen von dem angeklickten Node-Element benötigen, in diesem Fall den Wert der Key-Eigenschaft, speichern wir den Verweis auf das Node-Element in einer Variablen zwischen.
Diese deklarieren wir vorher wie folgt:
Dim objNode As MSComctlLib.Node
Dem Key-Wert entnehmen wir zwei Informationen: den als erstes Zeichen angegebenen Buchstaben, der den Typ des Elements liefert (zum Beispiel r für Root, k für Kunde, b für Bestellung oder p für Bestellposition) und die folgende Zahlenkombination, die dem Primärschlüsselwert des Datensatzes in der passenden Tabelle entspricht.
Diese Informationen sollen ebenfalls gespeichert werden, und zwar in den folgenden Variablen:
Dim strTyp As String Dim lngID As Long
Die folgenden Anweisungen ermitteln zunächst das angeklickte Element:
Set objNode = m_Treeview.HitTest(x, y)
Da HitTest den Wert Nothing übergibt, wenn kein Element angeklickt wurde, sondern ein leerer Bereich im TreeView-Steuerelement, prüfen wir vor den weiteren Schritten, ob objNode überhaupt mit einem Verweis auf ein angeklicktes Element gefüllt wurde und lesen dann die gewünschten Informationen aus:
If Not objNode Is Nothing Then strTyp = Left(objNode.Key, 1) lngID = Mid(objNode.Key, 2) End If
Damit ausgestattet können wir eine Select Case-Bedingung anlegen, die den Wert der Variablen strTyp prüft. In unserem Beispiel enthält strTyp einen der Werte r, k, b oder p. Um die übersichtlichkeit zu erhalten, rufen wir für jeden Wert eine eigene Prozedur zum Anzeigen des Kontextmenüs auf.
Diese heißen KontextmenueRootAnzeigen, KontextmenueKundenAnzeigen und so weiter. Alle Prozeduren außer das für das Root-Element nehmen den Primärschlüsselwert des angeklickten Elements als Parameter entgegen. Die vollständige Ereignisprozedur m_TreeView_MouseDown finden Sie in Listing 2.
Private Sub m_Treeview_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, _ ByVal y As stdole.OLE_YPOS_PIXELS) Dim strTyp As String Dim lngID As Long Dim objNode As MSComctlLib.Node Select Case Button Case acRightButton Set objNode = m_Treeview.HitTest(x, y) If Not objNode Is Nothing Then strTyp = Left(objNode.Key, 1) lngID = Mid(objNode.Key, 2) Select Case strTyp Case "k" KontextmenueKundeAnzeigen(lngID) Case "r" KontextmenueRootAnzeigen Case "b" KontextmenueBestellungAnzeigen(lngID) Case "p" KontextmenuePositionAnzeigen(lngID) End Select End If End Select End Sub
Listing 2: Aufrufen der Prozeduren zum Anzeigen der verschiedenen Kontextmenüs
Wir wollen mit dem Kontextmenü-Eintrag zum Löschen des aktuell angeklickten Kunden beginnen. Die entsprechende Prozedur heißt KontextmenueKundeAnzeigen und sieht wie in Listing 3 aus. Die Prozedur deklariert eine CommandBar– und eine CommandBarButton-Variable. Dann löscht sie ein eventuell bereits vorhandenes Kontextmenü namens TreeView_Kunde.
Private Sub KontextmenueKundeAnzeigen(lngID As Long) Dim cbr As Office.CommandBar Dim cbc As Office.CommandBarButton On Error Resume Next CommandBars("TreeView_Kunde").Delete On Error GoTo 0 Set cbr = CommandBars.Add("TreeView_Kunde", msoBarPopup, False, True) With cbr Set cbc = .Controls.Add(msoControlButton) With cbc .Caption = "Kunde löschen" .OnAction = "=KundeLoeschen(" & lngID & ")" End With .ShowPopup End With End Sub
Listing 3: Anzeigen des Kontextmenüs für einen Kunden, hier zunächst mit der Mögilchkeit zum Löschen des Kunden
Da dies einen Fehler auslösen kann, deaktiviert die Prozedur die integrierte Fehlerbehandlung für die Durchführung dieser Anweisung.
Anschließend fügt sie mit der Add-Methode der CommandBars-Auflistung ein neues Kontextmenü namens TreeView_Kunde hinzu. Dabei gibt sie mit dem ersten Parameter den Namen und mit dem zweiten den Menütyp an. Der dritte Parameter legt fest, dass es sich nicht um eine Menüleiste handelt und der vierte sorgt dafür, dass das Kontextmenü nur temporär erstellt wird – damit wird es beim Schließen von Access gelöscht.
Für das mit cbr referenzierte Kontextmenü fügt die Prozedur mit der Add-Methode der Controls-Auflistung einen neuen Kontextmenü-Eintrag hinzu. Der Typ wird mit dem Wert msoControlButton festgelegt. Anschließend stellt die Prozedur noch die beiden Eigenschaften Caption (Beschriftung) und OnAction ein. Letztere erwartet den Aufruf der beim Auswählen des Kontextmenü-Eintrags auszuführenden VBA-Funktion. Dieser soll gleich den Primärschlüsselwert des angeklickten TreeView-Elements übergeben, daher wird der Aufruf aus =KundeLoeschen, einer öffnenden Klammer, dem Primärschlüsselwert und einer schließenden Klammer zusammengesetzt – also zum Beispiel als =KundeLoeschen(123).
Die ShowPopup-Methode des CommandBar-Objekts zeigt das soeben erstellte Kontextmenü schließlich an (siehe Bild 3).
Bild 3: Anzeigen des Kontextmenüs für einen Kunden
Kunden löschen
Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein: