Warum noch ein Access-Buch?
Für wen ist das Buch?
Jetzt bestellen
+ direkter Download des eBooks!
Nur EUR 59,95!
Fehler gefunden?
Bitte melden!
Wünsche an das Buch?
Her damit!
Was denken die Leser über dieses Buch?
Lesen Sie aktuelle Rezensionen!
Kapitel des noch nicht veröffentlichten Buchs zum Downloaden, Probelesen und Kommentieren
Beispieldatenbanken
Zusätzliches Material

Das Buch im HTML-Format

Für unbestimmte Zeit bieten Addison-Wesley und André Minhorst den kompletten Inhalt des Buchs als Download an. Schauen Sie rein und informieren Sie sich über den Inhalt! Und wenn Ihnen das Buch nützlich erscheint und Sie glauben, dass Sie etwas gelernt haben oder durch das Gelesene sogar etwas Zeit und somit Geld bei Ihrer Arbeit einsparen konnten, können Sie sich ja beim Autor und beim Verlag revanchieren - beispielsweise durch den Kauf dieses Buchs.

Am schönsten wäre es natürlich, wenn Sie das Buch direkt hier bestellen - Sie erhalten das Buch dann direkt vom Verlag, und der Autor und Verlag haben dann noch mehr davon, als wenn Sie es anderswo kaufen.

Danke für Ihr Interesse!

5.11.8 Drag and Drop mit dem ListView-Steuerelement

5.11.9 Reihenfolge per Drag and Drop einstellen

Neben dem Bewegen von Elementen zwischen zwei ListView-Steuerelementen ist auch das Einstellen der Reihenfolge von Elementen ein häufig gefragtes Thema.

Dazu ist zunächst ein Feld in der Herkunftstabelle vorzusehen, das einen die Reihenfolge festlegenden Wert enthält - typischerweise heißt dieses Feld dann auch Reihenfolge.

Wichtig ist die Überlegung, wann die Änderungen der Reihenfolge im ListView in die zugrunde liegende Tabelle übertragen werden. Wenn man dies nach jeder Änderung erledigt, ist schon eine Menge Code notwendig. Daher beschränkt sich dieses Beispiel auf das Übertragen der Änderungen der Reihenfolge auf das Schließen des Formulars - das heißt, dass dann einmalig alle Elemente des ListViews durchlaufen und ihre neue Reihenfolge im Feld Reihenfolge der entsprechenden Tabelle vermerkt wird.

Aufbau des Formulars zum Einstellen der Reihenfolge per Drag and Drop

Das Formular frmListViewReihenfolge enthält ein ListView-Steuerelement namens lvwReihenfolge, das mit Daten aus der Tabelle tblPersonal gefüllt werden soll. Diese Tabelle enthält neben den eigentlichen Feldern ein Feld namens Reihenfolge. Das ListView-Steuerelement im Formular zeigt die Daten wie gehabt in der Ansicht lvwReport an. OLEDragMode und OLEDropMode stellen Sie auf 1 - ccOLEDragAutomatic beziehungsweise 1 - ccOLEDropManual ein. Da die Elemente mit der Maus verschoben werden sollen, wäre es gut, wenn man die Elemente über die ganze Spalte „greifen" könnte - dazu aktivieren Sie die Eigenschaft FullRowSelect. Das ListView-Steuerelement soll zwei Spalten anzeigen, deren Köpfe die Texte Nachname und Vorname enthalten.

Füllen des ListView-Steuerelements

Das Füllen des Steuerelements erfolgt beim Öffnen des Formulars in der Ereignisprozedur Form_Load. Die Routine erzeugt für jeden Datensatz ein Element im ListView, wobei die Startreihenfolge über die im Feld Reihenfolge festgelegten Zahlenwerte festgelegt ist. Der Inhalt dieses Feldes ist interessanterweise nicht Bestandteil der Elemente des ListView-Steuerelements. Der Grund ist, dass ein ListItem mit seinem Index bereits die aktuelle Reihenfolgeposition enthält.

Private Sub Form_Load()
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim objListitem As ListItem
    Set db = CurrentDb
    Set rst = CurrentDb.OpenRecordset("SELECT * FROM tblPersonal " _
        & "ORDER BY Reihenfolge", dbOpenDynaset)
    Do While Not rst.EOF
        Set objListitem = objListView.ListItems.Add(, "a" _
            & rst!PersonalID, rst!Nachname)
        objListitem.ListSubItems.Add , , rst!Vorname
        rst.MoveNext
    Loop
End Sub

Listing 5.39: Das ListView wird beim Öffnen des Formulars mit den Datensätzen der Tabelle tblPersonen gefüllt

Start des Drag-and-Drop-Vorgangs

Der Drag-and-Drop-Vorgang beginnt mit dem Markieren eines Elements mit der Maus und dem anschließenden Bewegen des Mauszeigers. Dies erkennt das Steuerelement und löst die Ereignisprozedur OLEStartDrag aus. Die Routine verwendet die Eigenschaft SelectedItem, um das markierte Element zu ermitteln. Dessen Daten werden durch ein »Pipe«-Zeichen (¦) getrennt in eine String-Variable geschrieben und dem Data-Parameter der Ereignisprozedur übergeben.

Private Sub lvwReihenfolge_OLEStartDrag(Data As Object, _
    AllowedEffects As Long)
    Dim strKey As String
    Dim objListitem As ListItem
    Set objListitem = objListView.SelectedItem
    strKey = objListitem.Key & "¦" & objListitem.Text & "¦" _
        & objListitem.ListSubItems(1).Text _
        & "¦" & objListitem.Index '& "¦" & objListitem.ListSubItems(2).Text
    Data.Clear
    Data.SetData strKey
End Sub

Listing 5.40: Ermitteln des markierten Elements und Zwischenspeichern seiner Daten

Von dort kann die Ereignisprozedur OLEDragDrop die Zeichenkette wieder auslesen (dazu später mehr). Erstmal tritt die Ereignisprozedur OLEDragOver auf den Plan. Diese wird regelmäßig während des Ziehens ausgelöst. Hier sorgt sie dafür, dass das Element, über dem sich der Mauszeiger aktuell befindet, markiert wird. So kann der Benutzer genau erkennen, wo das zu verschiebende Element landet:

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

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

End Sub

Listing 5.41: Diese Routine sorgt für das Markieren des Elements, über dem sich der Mauszeiger aktuell befindet

Drag-and-Drop-Vorgang abschließen

Das Loslassen der Maustaste beziehungsweise das »Droppen« löst die Ereignisprozedur OLEDragDrop aus. Zu diesem Zeitpunkt sind nun alle für die Operation notwendigen Informationen bekannt - nämlich das zu verschiebende Element und das Element, dessen Position es einnehmen soll. Die Daten des zu verschiebenden Elements entnimmt die Routine dem Data-Parameter der Ereignisprozedur - unter anderem auch den Index der vorherigen und der Zielposition.

Unter Umständen versucht der Benutzer, den Eintrag auf sich selbst zu ziehen - in dem Fall soll natürlich keine Änderung der Reihenfolge vorgenommen werden. Anderenfalls entfernt die Routine das Ausgangselement und legt es an der gewünschten Stelle neu an.

Außerdem wird die Boolean-Variable bolReihenfolgeGeaendert, die Sie im Übrigen modulweit und nicht in der Routine deklarieren, auf den Wert True gesetzt. Wozu diese Variable notwendig ist, erfahren Sie weiter unten.

Private Sub lvwReihenfolge_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
    Dim strData As String
    Dim strKey As String
    Dim strNachname As String
    Dim strVorname As String
    Dim lngReihenfolgeAlt As Long
    Dim lngIndex As Long
    Dim lngReihenfolgeNeu As Long
    Dim objListitem As MSComctlLib.ListItem
    strData = Data.GetData(ccCFText)
    strKey = Split(strData, "¦")(0)
    strNachname = Split(strData, "¦")(1)
    strVorname = Split(strData, "¦")(2)
    lngReihenfolgeAlt = CLng(Split(strData, "¦")(3))
    lngIndex = objListView.HitTest(x, y).Index
    lngReihenfolgeNeu = CLng(objListView.HitTest(x, y).Index)
    If Not lngReihenfolgeNeu = lngReihenfolgeAlt Then
        objListView.ListItems.Remove strKey
        Set objListitem = objListView.ListItems.Add(lngIndex, strKey, _
            strNachname)
        objListitem.ListSubItems.Add , , strVorname
        bolReihenfolgeGeaendert = True
    End If
End Sub

Listing 5.42: Diese Routine führt die eigentliche Drag-and-Drop-Operation durch

Neue Reihenfolge speichern

Fehlt noch der letzte Schritt: Die neue Reihenfolge soll beim Schließen des Formulars gespeichert werden. Damit dies nicht unnötig geschieht, also wenn etwa gar keine Änderung der Reihenfolge vorgenommen wurde, gibt es die oben erwähnte Boolean-Variable bolReihenfolgeGeaendert. Diese wird nur bei einer Änderung der Reihenfolge auf den Wert True gesetzt. Die Ereignisprozedur Form_Close fragt diese Variable beim Schließen des Formulars ab und speichert die neue Reihenfolge nur, wenn diese Variable den Wert True enthält.

Das Speichern ist ein Rundumschlag: Da die Anwendung nicht nachvollzieht, welche Elemente ihre Reihenfolge verändert haben, muss die Reihenfolge aller Elemente auf den neuesten Stand gebracht werden. Dazu durchläuft die Routine in einer For Each-Schleife alle Elemente und führt jeweils eine SQL-Update-Anweisung aus:

Private Sub Form_Close()
    Dim db As DAO.Database
    Dim objListitem As ListItem
    If bolReihenfolgeGeaendert = True Then
        Set db = CurrentDb
        For Each objListitem In objListView.ListItems
            db.Execute "UPDATE tblPersonal SET Reihenfolge = " _
                & objListitem.Index & " WHERE PersonalID = " _
                & Mid(objListitem.Key, 2)
        Next objListitem
    End If

    Set db = Nothing
End Sub

Listing 5.43: Speichern der neuen Reihenfolge in der zugrunde liegenden Tabelle der Datenbank

Nächster Abschnitt:

5.12 Das ImageList-Steuerelement

© 2006-2008 André Minhorst Alle Rechte vorbehalten.