Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Ihren XING-Kontakten zeigen

Diesen Beitrag Ihrem XING-Kontakten vorstellen

Diesen Beitrag auf Facebook teilen

Bisherige Kommentare:

Noch keine Kommentare vorhanden.

Alle Kommentare ansehen oder Kommentar abgeben

Über den Autor:

André Minhorst

Bitte nutzen Sie das XING-Profil nicht
für Fragen zum Artikel, sondern nur für
den Kontaktaustausch beziehungsweise
Projekt- oder Supportanfragen.

Zusammenfassung

Erfahren Sie, wie Sie Elemente im Treeview mit Drag and Drop verschieben.

Techniken

Formulare, Treeview-Steuerelement, VBA

Voraussetzungen

Access 2002 und höher oder Access 97/2000 und Developer Edition oder Visual Studio 6.0

Beispieldateien

Treeview2002.mdb

Drag and Drop im Treeview-Steuerelement

André Minhorst, Duisburg

Das Treeview-Steuerelement lässt sich sehr gut zur Darstellung von hierarchischen Daten verwenden. Im Gegensatz zu den üblichen Access-Steuerelementen unterstützt es auch Drag and Drop. Wie das im Detail funktioniert, erfahren Sie im vorliegenden Beitrag.

Drag and Drop aktivieren

Drag and Drop-Operationen erfordern je nach Anwendungsfall einige Zeilen Code. Voraussetzung ist, dass Sie die Einstellung für die Eigenschaften OLEDragMode auf ccOLEDragAutomatic und OLEDropMode auf ccOLEDropManual festlegen. Das können Sie im Eigenschaftsdialog des Treeview-Steuerelements erledigen (s. Abb. 1) oder per Code:

objTreeview.OLEDragMode = _
    ccOLEDragAutomatic

objTreeview.OLEDropMode = ccOLEDropManual

Kein Drag and Drop ohne VBA

Außerdem sind einige Ereignisprozeduren mit Leben zu füllen. Diese lassen sich nicht wie bei den üblichen Access-Steuerelementen über das Eigenschaftsfenster anlegen, sondern müssen direkt im VBA-Editor erstellt werden.

Abb. 1: Eigenschaften eines Treeview-Steuerelements

Dazu deklarieren Sie zunächst eine Objektvariable für das Treeview-Steuerelement, das Sie in der Beim Laden-Ereignisprozedur des Formulars zuweisen (s. Quellcode 1).

Quellcode 1: Deklarieren und Zuweisen des Treeview-Objekts

Dim objTreeview As MSComctlLib.Treeview

Private Sub Form_Load()

    Set objTreeview = Me.ctlTreeview.Object

End Sub

Allein durch die Deklarationszeile können Sie innerhalb der Prozeduren per IntelliSense auf die einzelnen Eigenschaften und Methoden des Treeview-Steuerelements zugreifen und dessen Ereignisprozeduren mit den beiden Kombinationsfeldern im Kopf des VBA-Codefensters anlegen.

Abb. 2: Anlegen von Ereignisprozeduren im VBA-Codefenster

Auf diese Weise sind die nachfolgend benötigten drei Prozeduren schnell erstellt (s. Abb. 2). Das Ereignis OLEStartDrag wird ausgelöst, wenn Sie den Mauszeiger auf einem Eintrag positionieren, die linke Maustaste gedrückt halten und den Mauszeiger dabei bewegen.

Das Ereignis OLEDragOver wird nach dem Ereignis OLEStartDrag in kurzen Abständen ausgelöst - es könnte eigentlich OLEDragMouseMove heißen -, bis Sie die Maustaste loslassen. Dies wiederum ruft das Ereignis OLEDragDrop auf den Plan.

Damit hätten Sie das Werkzeug beisammen - mit Ausnahme einiger nützlicher Eigenschaften des Treeview-Steuerelements:

  • HitTest(x,y): Liefert einen Verweis auf den Knoten mit den Koordinaten x und y.
  • SelectedItem: Legt den markierten Knoten fest oder liest diesen aus.
  • DropHighlight: Markiert den Knoten, über dem sich der Mauszeiger bei einer Drag and Drop-Operation befindet, sofern dies nicht der Ausgangsknoten ist.
  • Sobald Access den Start einer Drag and Drop-Operation erkennt, soll kein Knoten mehr markiert sein. Das erledigt der Einzeiler aus Quellcode 2.

    Aber warum soll die Markierung des aktuell ausgewählten Knotens aufgehoben werden? Ganz einfach: Dieser Knoten ist nicht unbedingt mit dem identisch, der per Drag and Drop verschoben werden soll.

    Dementsprechend wird in der während des Drag and Drop-Vorgangs immer wieder ausgeführten Ereignisprozedur OLEDragOver zunächst der zu verschiebende Eintrag über die Eigenschaft SelectedItem als aktueller Eintrag markiert.

    Dies passiert nur einmal direkt nach dem Starten des Drag and Drop-Vorgangs, nachdem die OLEStartDrag-Prozedur den vorherigen aktiven Knoten abgewählt hat.

    Bei jedem Aufruf der OLEDragOver-Prozedur passiert allerdings Folgendes: Mit der Eigenschaft DropHighlight wird der Knoten, über dem sich der Mauszeiger derzeit befindet, markiert, um ihn als Ziel der Operation zu kennzeichnen.

    Das große Finish folgt dann in der Ereignisprozedur OLEDragDrop. Diese wird beim Loslassen der Maustaste ausgelöst und muss dafür sorgen, dass der Knoten an die neue Stelle verschoben wird.

    Aber nicht nur das: Das Abbild der Daten im Treeview-Steuerelement und die in den Tabellen befindlichen Daten werden natürlich nicht automatisch synchronisiert.

    Also müssen Sie auch noch dafür sorgen, dass der entsprechende Datensatz an die neue Situation im Treeview-Steuerelement angepasst wird.

    Das hört sich zwar erst einmal recht kompliziert an, ist aber letzten Endes reine Fleißarbeit. Im vorliegenden Beispiel sieht die Routine wie in Quellcode 4 aus. Es gibt beim Drag and Drop grundsätzlich zwei zu unterscheidende Fälle:

  • Der Knoten wird in den leeren Raum gezogen und soll so in die oberste Hierarchie-Ebene eingeordnet werden.
  • Der Knoten wird auf einen anderen Knoten gezogen und soll so diesem untergeordnet werden.
  • Quellcode 2: Aufheben der aktuellen Markierung

    Private Sub ctlTreeview_OLEStartDrag(Data As Object, _
        AllowedEffects As Long)

        objTreeview.SelectedItem = Nothing

    End Sub

    Quellcode 3: Diese Routine wird immer wieder während des Drag and Drop-Vorgangs ausgeführt.

    Private Sub ctlTreeview_OLEDragOver(Data As _
        Object, Effect As Long, Button As _
        Integer, Shift As Integer, x As Single, _
        y As Single, State As Integer)

        If objTreeview.SelectedItem Is Nothing Then

            Set objTreeview.SelectedItem = objTreeview.HitTest(x, y)

        End If

        Set objTreeview.DropHighlight = objTreeview.HitTest(x, y)

    End Sub

    Nach dem Ermitteln einiger Informationen des Knotens, der verschoben werden soll (Primärschlüsselwert des entsprechenden Datensatzes, Key, angezeigter Text), zweigt eine If Then-Bedingung die Routine entsprechend den beiden oben genannten Fällen auf.

    Beim Ziehen in den leeren Raum wird zunächst der Knoten entfernt und neu angelegt. Leider nicht ohne Reibungsverluste, denn eventuell untergeordnete Knoten gehen so verloren. Um diese wiederherzustellen, wird die Änderung zunächst in der Tabelle Personal durchgeführt:

    Der Wert des Feldes Vorgesetzte(r) des verschobenen Datensatzes wird auf NULL gesetzt. Anschließend ruft die Routine die Prozedur TreeviewRekursivFuellen mit dem neuen Knoten als Parameter auf, um die untergeordneten Knoten wiederherzustellen.

    Diese Routine wird auch zum Aufbauen eines Baumes auf Basis von Daten aus Tabellen mit reflexiver Beziehung verwendet - mehr dazu im Beitrag Treeview-Steuerelement mit Daten füllen (s. Shortlink 321).

    Zieht der Benutzer den Knoten auf einen anderen Knoten, ist etwas weniger zu tun:

    Nach einer Prüfung, ob der Knoten nicht auf sich selbst abgelegt werden soll, ermittelt die Routine zunächst den Primärschlüsselwert des neuen übergeordneten Knotens.

    Anschließend weist man der Parent-Eigenschaft des verschobenen Knotens den neuen übergeordneten Knoten zu. Damit werden auch automatisch alle untergeordneten Knoten mitgezogen.

    Fehlt noch die Übernahme der Änderung in die Datenbank mit der entsprechenden UPDATE-Abfrage.

    Das Formular inklusive Drag and Drop-Funktionalität sollte nun wie in Abb. 3 aussehen und das Verschieben der Einträge im Treeview-Steuerelement ermöglichen. Für jede Verschiebung tragen die entsprechenden Routinen die Änderungen in die dem Treeview-Steuerelement zugrunde liegende Tabelle ein.

    Abb. 3: Drag and Drop in Aktion

    Quellcode 4: Durchführen der Drag and Drop-Operation

    Private Sub ctlTreeview_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, _
        Shift As Integer, x As Single, y As Single)

        Dim db As DAO.Database

        Dim lngID As Long

        Dim lngParentID As Long

        Dim strKey As String

        Dim strText As String

        Set db = CurrentDb

        'zu verschiebenden Datensatz ermitteln

        lngID = Mid(objTreeview.SelectedItem.Key, 9)

        strKey = objTreeview.SelectedItem.Key

        strText = objTreeview.SelectedItem.Text

        'Wurde an eine freie Stelle oder auf einen anderen Knoten gezogen?

        If objTreeview.HitTest(x, y) Is Nothing Then

            'Knoten entfernen

            objTreeview.Nodes.Remove objTreeview.SelectedItem.Index

            'Knoten neu anlegen

            objTreeview.Nodes.Add , , strKey, strText, 1

            'Änderung in die Datenbank übertragen

            db.Execute "UPDATE Personal SET [Vorgesetzte(r)] = NULL WHERE [Personal-Nr] = " & lngID

            'Untergeordnete Elemente des verschobenen Knotens wiederherstellen

            TreeviewRekursivFuellen lngID

        Else

            If objTreeview.SelectedItem <> objTreeview.DropHighlight Then

                'neuen übergeordneten Datensatz ermitteln

                lngParentID = Mid(objTreeview.DropHighlight.Key, 9)

                'Zielknoten als neuen übergeordneten Knoten festlegen

                Set objTreeview.SelectedItem.Parent = objTreeview.DropHighlight

                'Änderung in die Datenbank übertragen

                db.Execute "UPDATE Personal SET [Vorgesetzte(r)] = " _
                    & lngParentID & " WHERE [Personal-Nr] = " & lngID

            End If

            Set objTreeview.DropHighlight = Nothing

        End If

    End Sub

    Zusammenfassung und Ausblick

    Mit der Drag and Drop-Operation in Zusammenhang mit dem Treeview-Steuerelement lassen sich hierarchische Daten ganz einfach mit der Maus zuordnen.

    Das vorliegende Beispiel bezieht sich auf ein Treeview-Steuerelement, das mit Daten aus einer Tabelle mit reflexiver Beziehung gefüllt wurde.

    Die Vorgehensweise bei Treeviews mit Daten aus mehreren verknüpften Tabellen unterscheidet sich zwar von dem hier vorgestellten Beispiel, kann aber mit dem enthaltenen Know-how nachgebildet werden.

    Natürlich fehlen dem Beispiel noch Features: So sollten Knoten, die in den freien Raum gezogen werden, eigentlich direkt in alphabetischer Reihenfolge eingeordnet anstatt einfach unten angehängt werden.

    Kommentare und Ergänzungen

    Wenn Sie Kommentare, Fragen oder Ergänzungen zu diesem Artikel haben, können Sie diese hier eintragen. Wir bemühen uns, kurzfristig auf Ihren Kommentar einzugehen.

    Ihr Name:

    Ihre E-Mail-Adresse (für
    Rückfragen, wird nicht veröffentlicht:

    Betreff:

    Ihr Kommentar zu diesem Artikel:

    © 2003-2010 André Minhorst Alle Rechte vorbehalten.