Access
 sql >> Datenbank >  >> RDS >> Access

ListView-Steuerelement Drag-Drop-Sortierungsereignisse

Datenzeilen im ListView-Steuerelement neu anordnen.

In der früheren Episode dieses Tutorials haben wir gelernt, wie man die Spalten neu anordnet, indem man diese Funktion aktiviert:AllowColumnReorder Option auf dem Eigenschaftsblatt. Das Verschieben einer Zeile erfolgt jedoch durch Ziehen und Platzieren in einer anderen Zeile. Zum Neuanordnen der ListView-Steuerelementzeilen erfordert die ListItem-Drag-and-Drop-Aktion die Aktivierung dieser Funktion auf dem Eigenschaftenblatt. Aber das allein wird nicht funktionieren, benötigt VBA-Code, um das Element in der erforderlichen Reihenfolge neu anzuordnen.

Lassen Sie uns für diese Übung ein Beispiel-Zugriffsformular mit Steuerelementen und VBA-Code in unserer Datenbank erstellen. Das Beispielbild des Formulars mit ListBox- und ListView-Steuerelementen ist unten angegeben.

Wir haben eine Liste von Tabellen und Abfragen (keine Aktionsabfragen) im Listenfeld erstellt. Wenn Sie eines der Listenelemente auswählen, werden die Datensätze sofort im ListView-Steuerelement angezeigt, so wie wir sie in der DataSheet-Ansicht sehen.

Die Designaufgabe.

  1. Erstellen Sie eine neue Tabelle mit einem einzelnen Textfeld mit dem Feldnamen DataList .

  2. Speichern Sie die Tabelle unter dem Namen lvTables (lv steht für ListView).

  3. Öffnen Sie die Tabelle in der Datenblattansicht.

  4. Fügen Sie einige Tabellennamen hinzu und wählen Sie Abfragenamen aus Ihrer Datenbank in die Tabelle aus. Ich habe Tabellen aus der Northwind-Beispieldatenbank für meine Liste importiert.

    Hinweis: Der Anhang Das Feld ist im ListView-Steuerelement nicht gültig. Erstellen Sie Auswahlabfragen für Tabellen mit Anhangsfeld und wählen Sie alle Felder außer dem Anhangsfeld aus.

  5. Erstellen und öffnen Sie ein neues Formular in der Entwurfsansicht.

  6. Fügen Sie ein ListBox-Steuerelement in das Formular ein, zeigen Sie das Eigenschaftenblatt an und ändern Sie seinen Namen Eigenschaftswert in List0 .

  7. Ändern Sie das untergeordnete Label Bildunterschrift Wert in Tabellen .

  8. Zeigen Sie das Eigenschaftenblatt des ListBox-Steuerelements an und legen Sie die Zeilenquelle fest Eigenschaftswert zu den lvTables Name.

  9. Überprüfen Sie, ob der Zeilenquelltyp auf Tabelle/Abfrage eingestellt ist und der Eigenschaftswert der gebundenen Spalte 1 ist. Wenn anders, dann ändern.

  10. Fügen Sie ein ListView-Steuerelement aus der Liste der ActiveX-Steuerelemente ein und ändern Sie seinen Namenseigenschaftswert in ListView1 .

  11. Passen Sie die Größe beider Steuerelemente an, wie auf dem oben angegebenen Demo-Formularbild gezeigt.

  12. Fügen Sie über den Steuerelementen eine Beschriftung ein und ändern Sie die Eigenschaftswerte Name und Beschriftung in Überschrift. Der Beschriftungswert wird vom VBA-Code geändert, wenn eine Tabelle oder Abfrage aus der ListBox ausgewählt wird.

  13. Erstellen Sie unterhalb der Steuerelemente eine Befehlsschaltfläche und ändern Sie deren Name-Eigenschaftswert in cmdClose und den Caption-Eigenschaftswert auf Close .

  14. Klicken Sie mit der rechten Maustaste auf das ListView-Steuerelement, markieren Sie das ListViewCtrl-Objekt Option und wählen Sie Eigenschaften .

  15. Ändern Sie die Eigenschaftseinstellungen so, dass sie mit den Einstellungen in Allgemein übereinstimmen Registerkartenbild unten angegeben.

  16. Abbildung des Eigenschaftsblatts des ListView-Steuerelements – Allgemeine Registerkartenansicht ist unten angegeben:

    Einige dieser Optionen haben wir bereits in früheren Sitzungen festgelegt. Hier benötigen wir für unsere Drag-Drop-Aktion folgende Optionen:

    • OLEDragAutomatisch - 1

    • OLEDropManual - 1

    • FullRowSelect - True

    • HotTracking – Richtig

Stellen Sie sicher, dass die obigen Einstellungen mit Ihrem Eigenschaftsblatt übereinstimmen, und speichern Sie dann das Formular.

Zeigt das VBA-Modul des Formulars an.

Der Formularmodul-VBA-Code.

Kopieren Sie den folgenden VBA-Code und fügen Sie ihn in das Modul ein, wobei Sie die vorhandenen Codezeilen überschreiben, falls vorhanden:

Option Compare Database
Option Explicit

Dim lvwList As MSComctlLib.ListView
Dim strTable As String
Dim db As DAO.Database
Dim rst As DAO.Recordset

Private Sub Form_Load()
    Set lvwList = Me.ListView1.Object

End Sub


Private Sub Form_Unload(Cancel As Integer)
On Error GoTo Form_Unload_Err
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim flag As Boolean
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)
flag = False
For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) _
       And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

Form_Unload_Exit:
Exit Sub

Form_Unload_Err:
MsgBox Err & " : " & Err.Description, , "Form_Unload()"
Resume Form_Unload_Exit

End Sub

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control
' sorts the data of that column. On the first Click on the Column
'will sort in Ascending Order, second Click will sort in Descending
With Me.ListView1
    ' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
' Set Sorted to True to sort the list.
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 
    .Sorted = True
End With

End Sub

Private Sub List0_Click()

strTable = List0.Value

Call LoadListView(strTable)

End Sub

Private Sub LoadListView(ByVal s_Datasource As String)
On Error GoTo LoadListView_Err
    Dim j As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim strHeading As String
    
    strHeading = UCase(s_Datasource)
    With Me.Heading
        .caption = strHeading
        .FontName = "Courier New"
        .FontSize = 20
        .FontItalic = True
        .FontBold = True
    End With
    
   'Initialize ListView Control
    lvwList.ColumnHeaders.Clear
    lvwList.ListItems.Clear
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(s_Datasource, dbOpenSnapshot)
       
    'Initialize ListView & Column Headers Property Values
     With lvwList
        .Font.Size = 10
        .Font.Name = "Verdana"
        .Font.Bold = False
        .GridLines = True
    End With
    
    With lvwList
        'Syntax: .ColumnHeaders.Add Index, Key, Text, Width in Pixels, Alignment, Icon
       For j = 0 To rst.Fields.Count - 1
        .ColumnHeaders.Add , , rst.Fields(j).Name, IIf(j = 0, 3000, 1400), 0
       Next
    End With
   Dim I As Long
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
    'Syntax: lvwList.ListItems.Add Index, Key, Text, Icon, SmallIcon
        Set tmpLItem = lvwList.ListItems.Add(, , rst.Fields(0).Value) 'Name column
        
         'Syntax: tmpLItem.ListSubItems.Add Index, Key, Text, ReportIcon, ToolTipText
          With tmpLItem
                For j = 1 To rst.Fields.Count - 1
                    .ListSubItems.Add , , Nz(rst.Fields(j).Value, "")
                Next
          End With
        rst.MoveNext
    Loop
    rst.Close
    
    With lvwList
        If .ListItems.Count > 0 Then
            .ListItems(1).Selected = True
        End If
    End With
  
    Set db = Nothing
    Set rst = Nothing
    
LoadListView_Exit:
Exit Sub

LoadListView_Err:
MsgBox Err & " : " & Err.Description, , "LoadListView()"
Resume LoadListView_Exit
End Sub


Private Sub ListView1_OLEDragOver(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)

End Sub

Private Sub ListView1_OLEDragDrop(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dropped
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being readded to the list
Dim lvwTarget As ListItem
'Subitem reference in dropped item
Dim lvwSub As ListSubItem
'Drop position
Dim intTgtIndex As Integer
Dim j As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

'Ignore overlapping drag or drop Item actions
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

'Save the droped position Index Number
intTgtIndex = lvwDrop.Index
'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'For j = intTgtIndex To ListItems.Count
    
'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

'Destroy all objects
Set lvwTarget = Nothing
Set lvwDrag = Nothing
Set lvwDrop = Nothing
Set lvwList.DropHighlight = Nothing

End Sub

Private Sub cmdClose_Click()
    DoCmd.Close acForm, Me.Name
End Sub

Sie sind mit dem obigen VBA-Code vertraut, mit Ausnahme der neu hinzugefügten Unterroutinen:ListView1_OLEDragOver(), ListView1_OLEDragDrop(), Form_Unload(), und die ListView1_ColumnClik() Verfahren. Die ersten beiden Verfahren helfen uns, ein Element (Zeile) zu ziehen und über ein anderes Element abzulegen, um es an einer neuen Position einzufügen. Die Prozeduren Form_Unload() und ListView1_ColumnClick() sortieren die Items.

Die folgenden Bilder zeigen die Drag-and-Drop-Aktion in Sequenzen ihrer Ausführung

Das erste Bild unten zeigt die Drag-and-Drop-Aktionssequenz. Das ListItem mit der EmployeeID 7 wird vom Benutzer nach oben gezogen und über dem ListItem mit der ID 3 abgelegt.

Das zweite Bild zeigt die Bewegung von ListItem in umgekehrter Reihenfolge.

Wenn sich der Mauszeiger über eine Zeile mit dem gezogenen Element bewegt, wird zwischen der Quell- und der Zielzeile auf dem Weg nach oben nacheinander hervorgehoben.

Die Drag-and-Drop-Aktion in Bildern.

Die Zeile mit der Mitarbeiter-ID 7 wird auf dem Element mit der Mitarbeiter-ID 3 oben abgelegt.

Die segmentweise Analyse des VBA-Codes.

Bei einer Elementauswahl aus der ListBox wird die Ereignisprozedur List0_Click() ausgeführt und die Datensätze in das ListView-Steuerelement geladen.

Private Sub List0_Click()
Dim strTable As String

strTable = List0.Value

  Call LoadListView(strTable)

End Sub

Der ausgewählte Tabellen-/Abfragename wird in der strTable gespeichert String-Variable. Die LoadListView() Unterroutine wird mit der Variablen strTable als Parameter ausgeführt. Wir sind diesen Kodex in früheren Sitzungen mehr als einmal durchgegangen, und Sie können diese Seiten über die Links am Ende dieser Seite besuchen, um weitere Informationen zu erhalten. Möglicherweise finden Sie einige geringfügige Änderungen, die ich an diesem Kodex vorgenommen habe.

Wir haben das ImageList Control in dieser Episode nicht verwendet, das Icon, SmallIcon Parameterwerte in der Methode ListItems.Add() und ReportIcon, TooltipText Parameterwerte in der Methode ListSubItems.Add() werden ebenfalls nicht verwendet.

Sehen wir uns an, was in ListView1_OLEDragOver() passiert und ListView1_OLEDragDrop() VBA-Codesegmente.

Die ListView1_OLEDragOver() Prozedur.

Private Sub ListView1_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)
End Sub 

Dieses Verfahren wird automatisch ausgeführt, wenn Sie versuchen, auf eine Zeile zu klicken und sie gedrückt zu halten, zu ziehen und sich auf dem Weg zur Zielzeile über andere Zeilen zu bewegen. Die Ziehaktion bewegt sich über eine andere Zeile und wird hervorgehoben.

Der ListView1.HitTest(x, y) liest die x-, y-Koordinaten, die die Zeilenposition auf dem ListView-Steuerelement bestimmen, und hebt diese Zeile hervor. Dieser Vorgang wird fortgesetzt, wenn Sie sich über anderen Zeilen befinden, bis Sie es auf der Zielzeile ablegen, indem Sie die Maustaste loslassen. Die Drop-Aktion löst ListView1_OLEDragDrop() aus Prozedur und führt die Wechselprozeduren der Quellzeile aus.

Das ListView1_OLEDragDrop-Verfahren.

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

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem 'Drop position index Dim intTgtIndex As Integer Set lvwDrop = lvwList.HitTest(x, y) 'save the source item Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item 'Ignore overlapping drag or drop Item actions If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If 'Save the droped position Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True 'Destroy all objects Set lvwTarget = Nothing Set lvwDrag = Nothing Set lvwDrop = Nothing Set lvwList.DropHighlight = Nothing End Sub

Lassen Sie uns dieses Verfahren Schritt für Schritt durchgehen und verstehen, was dort passiert. Das folgende Codesegment deklariert notwendige Objektvariablen, um die Drag-and-Drop-Aktion zu handhaben:

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Reference of the Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem
'Drop position index
Dim intTgtIndex As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

Die ersten drei temporären ListItem-Objekte werden mit unterschiedlichen Namen deklariert.

Der lvwDrag Das ListItem-Objekt enthält die Kopie der Zeile, die wir auswählen, um sie an eine neue Position zu ziehen.

Der lvwDrop Das ListItem-Objekt speichert die Referenz der Zeile, auf der wir das gezogene Listenelement ablegen.

Während der Umstellung der ListItems-Aktion löschen wir das Quellelement von seinem ursprünglichen Speicherort und erstellen es dann am Zielspeicherort mit der Quell-ListItem-Indexnummer. Die Referenzen dieses neuen ListItems werden im lvwTarget gespeichert ListItem-Objektvariable.

Das lvwSub Variable, die als sequenzierende Objektvariable in For deklariert ist. . .Weiter Schleife. Diese Schleife erfordert, dass die ListSubItems (ab der 2. Spalte) nacheinander vom lvwDrag-Objekt durchlaufen werden. Obwohl wir das ursprüngliche ListItem gelöscht haben, haben wir eine Kopie davon im lvwDrag ListItem-Objekt gespeichert.

Die lvwDrop ListItem-Indexnummer wird im intTgtIndex gespeichert Variable.

Der lvwList.HitTest(x, y) Die Funktion liest die x-, y-Koordinaten des ListView-Steuerelements und identifiziert das Ziel-ListItem, wo wir das Quell-ListItem abgelegt haben, und erstellt eine Kopie davon im lvwDrop-Objekt.

Wir werden zuerst ein ListItem auswählen, bevor wir es an die neue Position ziehen.

Das lvwList.SelectedItem Property wird auf True gesetzt. Mit Hilfe dieses Eigenschaftsstatus kopieren wir das ausgewählte ListItem in das lvwDrag ListItem-Objekt. Das nächste Codesegment validiert sowohl Quell- als auch Ziel-ListItem-Objekte.

Validierungsprüfungen für die Drag-Drop-Aktion.

'Ignore overlapping drag or drop Item actions, 
'OR drag and drop happens on the same ListItem.
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing)  Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

Das obige Codesegment validiert die Drag-and-Drop-Aktion. Wenn diese Aktionen nicht mit einem gültigen Element gestartet oder beendet wurden, sind die lvwDrop- oder lvwDrag-Objekte oder beide leer. Oder eine andere ungültige Bewegung kann passieren, wenn der Benutzer eine Zeile nach oben oder unten bewegt, aber seine Meinung ändert und sie wieder in dieselbe Zeile fallen lässt. Die Erkennung solcher falscher Bewegungen beendet das Programm.

Wenn sich der obige Test als gültig erweist, fährt das Programm mit der Ausführung der nächsten Prozedur fort, um die Zeilen neu anzuordnen.

'Save the dropped position ListItem Index Number
intTgtIndex = lvwDrop.Index

'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

Die Aktionen der obigen neun Zeilen ausführbaren Codes (andere Zeilen sind Kommentare) sind etwas unkompliziert.

Der intTgtIndex =lvwDrop.Index -Anweisung speichert die Indexnummer des Ziel-ListItems in intTgtIndex Variable.

Da wir das Source Row listItem bereits im temporären Objekt lvwDrag gespeichert haben, besteht der nächste Schritt darin, das Source ListItem aus dem ListView Control zu entfernen. Die ListItems.Remove()-Prozedur aufgerufen, mit der Anweisung lvwList.ListItems.Remove lvwDrag.Index .

Kurz gesagt, die Drag-Drop-Aktion besteht darin, ein ListItem von seiner ursprünglichen Position zu löschen und es an der Zielposition mit der Indexnummer der Zielzeile erneut zu erstellen.

Die Anweisung Set lvwTarget =lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) erstellt das neue ListItem mit seiner Zielpositionsindexnummer intTgtIndex und dem Text Wert von Source ListItem, der zuvor im lvwDrag-Objekt gespeichert wurde.

Bei der erstmaligen Erstellung des ListItems haben wir nur diese beiden Werte, den Index und den Text verwendet Parameterwerte. Die anderen Parameteroptionen Key, Icon, haben wir nicht verwendet und SmallIcon andernfalls müssen wir diese Parameterwerte auch aus dem lvwDrag-Objekt einschließen.

Gemäß unseren oben gezeigten Drag-Drop-Beispielbildern haben wir das 7. ListItem verschoben und auf dem 3. ListItem abgelegt. Danach haben wir das 7. Item (oder Source ListItem) aus dem ListView Control gelöscht. Erstellt ein neues ListItem mit der Zielindexnummer 3.

Jetzt gibt es zwei Elemente mit der gleichen Indexnummer 3, das vorhandene mit der Indexnummer 3 und das neu erstellte mit der Indexnummer 3. Alle anderen Informationen werden aus dem lvwDrag-Objekt (oder dem 7. ListItem, das in lvwDrag gespeichert ist) übernommen Einspruch früher).

Das System inkrementiert automatisch das vorhandene ListItem 3 weiter zu den nächsten Sequenznummern 3,4,5 . . . bis 4,5,6 . . . und verschiebt sie nach vorne, um Platz für das eingehende Element zu schaffen, das dazwischen eingefügt werden kann.

Die Auswirkungen des Löschens einer Zeile und des Erstellens an anderer Stelle.

Nehmen Sie an, dass wir diese Bewegung in umgekehrter Reihenfolge machen, wie Listeneintrag Nr. 3 von oben ziehen und auf Eintrag Nr. 7 fallen lassen, was passiert dann?

Natürlich werden wir den 3. Artikel löschen und versuchen, am neuen Ort einen neuen Artikel mit der Indexnummer 7 zu erstellen. Wenn Artikel Nummer 3 gelöscht wird, verschiebt sich Artikel Nummer 4 aufwärts oder 4,5,6,7,8,9 wird zu 3,4,5,6,7,8 (um alle Artikel der Reihe nach zu machen) oder früher Element mit der Indexnummer 7 wird zu 6.

Wenn wir den neuen Artikel mit der Indexnummer 7 erstellen, wird die vorhandene 7,8 wieder zu 8,9. Wenn wir die Bewegung von Zeilen beim Löschen und Erstellen von Zeilen beobachten, verschiebt das erste Beispiel die Zielzeile nach unten, um Platz für das eingehende Element zu machen. Im zweiten erklärten Beispiel (Verschieben von 3 nach 7) wird die Zielzeile nach oben verschoben.

Hinweis: Ansehen der Mitarbeiter-ID-Wert für seine Platzierung als Anhaltspunkt dafür, dass ListItem nach unten oder oben verschoben wird, wenn wir ListItem neu anordnen.

Ich habe ListItem überall in Drag-Drop-Operationen erwähnt. Das ListItem bezieht sich nur auf die erste Spalte der ListView-Zeile. Andere Spaltenwerte sind ListSubItems oder die untergeordneten Elemente des ListItem. Das bedeutet, dass Sie nur die erste Spalte ziehen und ablegen können. Andere Spalten oder ListSubItems werden mit VBA-Code unter das ListItem verschoben.

Dies gilt, wenn Sie die FullRowSelection nicht aktiviert haben auf dem Eigenschaftsblatt des ListView-Steuerelements auf Allgemein Tab.

Wenn diese Option aktiviert ist, können Sie jede Spalte auswählen, aber das System bezieht sich auf den ListItem-Index für die Neuordnung der Zeilen. Vergleichen Sie die beiden obigen Bilder mit einem anderen Satz von zwei Beispielbildern, dem dritten und vierten Bild von oben auf dieser Seite.

Die Drag-and-Drop-Aktion funktioniert nicht, wenn die folgenden beiden Eigenschaftswerte nicht auf dem Eigenschaftenblatt des ListView-Steuerelements unter Allgemein festgelegt sind Tab.:

  • ccOLEDragAutomatic =1
  • ccOLEDropManual =1

Die nächsten fünf Anweisungen verschieben die ListSubItems, falls vorhanden, zu dem am neuen Ort neu erstellten ListItem.

Als nächstes wird das neu erstellte ListItem hervorgehoben.

Als nächstes werden alle erstellten temporären Objekte aus dem Speicher gelöscht.

Hinweis: Ein weiterer wichtiger Punkt, der hier zu beachten ist, ist, dass diese Anordnung temporär ist und verloren geht, wenn Sie das Formular schließen oder eine andere Tabelle/Abfrage auf das ListView-Steuerelement laden.

Wenn wir möchten, dass die geänderte Reihenfolge von ListItems dauerhaft bleibt oder bis die Reihenfolge das nächste Mal geändert wird, müssen wir in der Lage sein, die aktuelle indizierte Bestellnummer in der Tabelle selbst zu aktualisieren. Wir haben ein neues Integer-Feld mit der Feldnamen-ID in der Employees-Tabelle hinzugefügt.

Der Beispielbildschirm mit den in alphabetischer Reihenfolge neu angeordneten Mitarbeiterdaten ist unten angegeben:

Da das Feld Mitarbeiter-ID ein AutoWert-Feld ist und mit anderen zugehörigen Tabellen verknüpft ist, haben wir ein neues Zahlenfeld mit dem Feldnamen ID hinzugefügt. Dieser Feldwert wird anfangs manuell mit denselben Sequenznummern aus der Mitarbeiter-ID festgelegt. Dieser Feldwert wird anfänglich in dieser Reihenfolge sein. Aber die ListView-Zeilendaten können ihre Reihenfolge ändern, wenn Sie die Daten auf dem ListView-Steuerelement aufgrund von Drag-and-Drop-Aktionen neu anordnen.

Sehen Sie sich die MitarbeiterQ an Fragen Sie die unten angegebene SQL ab:

SELECT [FirstName] & " " & [LastName] AS EmployeeName, 
Employees.ID, 
Employees.EmployeeID, 
Employees.TitleOfCourtesy, 
Employees.Title, 
Employees.Address, 
Employees.City, 
Employees.Region, 
Employees.PostalCode, 
Employees.Country, 
Employees.HomePhone, 
Employees.Extension, 
Employees.Notes
FROM Employees
ORDER BY Employees.ID;

Die obige Abfrage wird als Datenquelle für das ListView-Steuerelement verwendet und sie werden nach dem ID-Feld sortiert. Das ID-Feld wird mit der geänderten Reihenfolge der Indexnummern im ListView-Steuerelement aktualisiert. Der Aktualisierungsprozess wird von Form_Unload() ausgeführt Ereignisprozedur beim Schließen des Formulars. Diese Methode stellt sicher, dass beim nächsten Öffnen des ListView-Steuerelements die Daten in der Reihenfolge vorliegen, in der Sie sie beim letzten Mal neu angeordnet haben.

Das Form_Unload() VBA-Code für Ereignisprozedur.

Private Sub Form_Unload(Cancel As Integer)
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)

For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text 'EmployeeName
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp 'replace ID number
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

End Sub

Überprüfen Sie den EmployeeName Feldwert im obigen Bild. Sie sind in alphabetischer Reihenfolge angeordnet. Der neue ID-Feldwert in der Employees-Tabelle wird mit ihrer aktuellen ListView Control ListItem-Indexnummernfolge aktualisiert.

Wenn Sie die folgenden Punkte beachten, können Sie leicht verstehen, was wir mit dem obigen Code machen:

  1. Der Text des ListItems (erste Spalte). Parameterwert ist der Name des Mitarbeiters und in alphabetischer Reihenfolge angeordnet.

  2. Die ListItems im ListView-Steuerelement haben Indexnummern von 1 bis 9 in der Reihenfolge, in der sie auf dem Bildschirm angezeigt werden, d. h. die Indexnummer des ersten Elements ist 1 und die Indexnummer des letzten 9. Die ursprünglichen Daten im ID-Feld der Employees-Tabelle sind es nicht in dieser Reihenfolge.

  3. Wir nehmen den Text Wert (Employee Name) des ersten ListItems und suchen Sie nach dem Namen in der Tabelle.

  4. Wenn der Datensatz gefunden wird, wird die Indexnummer des aktuellen ListItem im ID-Feld der Tabelle aktualisiert (ersetzt).

  5. Dieser Vorgang wurde für alle verbleibenden Datensätze in der Tabelle wiederholt.

Lassen Sie uns den VBA-Code durchgehen. Am Anfang prüfen wir, ob die Source data Table/Query in das ListView Control geladen wurde oder nicht?

Wenn die strTable Die Variable wird nicht mit dem Abfragenamen initialisiert, dann ist das ListView-Steuerelement leer. Wenn dies der Fall ist, hat der Benutzer das Formular geöffnet und geschlossen, ohne den Abfragenamen auszuwählen, um die Daten in das ListView-Steuerelement zu laden. Das Form_Unload Die Ereignisprozedur wird an dieser Stelle abgebrochen und das Formular geschlossen.

Wenn das ListView-Steuerelement Daten enthält, wird der nächste Schritt ausgeführt und die Quelldatenabfrage EmployeesQ zum Aktualisieren geöffnet.

Der nächste Schritt besteht darin, jedes ListItem durchzugehen und die Indexnummer im ID-Feld des Employees-Datensatzes zu aktualisieren.

Zuerst wird die aktuelle Zeilenindexnummer im tmp gespeichert Variable.

Der erste lvwList.ColumnHeader-Name EmployeeName und den Namen des Mitarbeiters wird aus ListItem.Text entnommen in einen Ausdruck in den Kriterien String-Variable, wie EmployeeName ="Andrew Fuller".

Die rst.FindFirst-Kriterien Der Befehl durchsucht die Quelldatentabelle, um den Datensatz mit dem angegebenen Namen zu finden. Wenn der Datensatz gefunden wird, wird die aktuelle ListItem-Indexnummer im ID-Feld aktualisiert.

Dieser Vorgang wird für alle Zeilen des ListView-Steuerelements wiederholt, und wenn er fertig ist, wird das Formular geschlossen.

Wenn Sie das nächste Mal die Datensätze aus dieser Abfrage in das ListView-Steuerelement laden, werden sie in derselben Reihenfolge angezeigt, in der Sie das Formular das letzte Mal geschlossen haben.

Hinweis:Die Abfrage wurde hier notwendig, um die Daten auf dem ID-Feld zu sortieren und sie in der geänderten Reihenfolge auf dem ListView-Steuerelement anzuzeigen.

All diese Arbeit diente dazu, die Daten in der zuletzt sortierten Reihenfolge zu speichern, damit beim nächsten Öffnen des Formulars die Daten im ListView-Steuerelement in dieser Reihenfolge angezeigt werden.

Windows Explorer-ähnliche Sortiermethode.

Im Windows Explorer können Sie die angezeigte Liste in aufsteigender oder absteigender Reihenfolge sortieren, indem Sie auf eine beliebige Spaltenüberschrift klicken. Die Spaltenüberschrift funktioniert wie eine Umschaltfläche. Wiederholtes Klicken auf die Spaltenüberschrift sortiert die Spaltendaten in aufsteigender/absteigender Reihenfolge nach dem folgenden ListView1_ColumnClick() Ereignisverfahren:

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control is
' sorted by the subitems of that column.

With Me.ListView1
' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 ' Set Sorted to True to sort the list.
     .Sorted = True
End With
End Sub

Hinweis: Die Sortierung aller Daten erfolgt nur im Textvergleichsmodus. Die ListItems und ListSubItems Hinzufügen() der dritte Parameter der Methode, die angezeigten Informationen auf dem ListView-Steuerelement sind Text Typ. Datums- und numerische Werte werden alle nur als Text behandelt.

Windows Explorer speichert die zuletzt sortierte Reihenfolge der Elemente im Ordner. Wenn wir diesen Ordner erneut öffnen, wird die Liste in der früheren sortierten Reihenfolge angezeigt.

Mit dem Form_Unload() Ereignisverfahren Diese Funktion des Windows Explorers wird in der Mitarbeitertabelle möglich. Wenn Sie das Formular nach dem Sortieren nach einer beliebigen Spalte schließen, wird diese indizierte Bestellsequenz in der Mitarbeitertabelle im ID-Feld gespeichert. Die EmployeesQ-Abfrage sortiert die Daten beim Öffnen immer nach dem ID-Feld.

Die Demo-Datenbank ist zum Download beigefügt. Es gibt zwei Demoformulare in der Datenbank. Das erste Formular zeigt das Öffnen von Tabellen und Abfragen im ListView-Steuerelement, um die Daten in der Datenblattansicht anzuzeigen. Das zweite Formular verwendet nur das EmployeesQ Abfrage allein zum Ziehen, Ablegen, Sortieren und Speichern der letzten Sortierreihenfolge von Daten für die zukünftige Verwendung.



  1. ActiveX ListView Control Tutorial-01.
  2. ListView Control Tutorial-02.
  3. Zuweisen von Bildern zu ListView-Elementen.
  4. Drag-Drop-Sortierungsereignisse des ListView-Steuerelements
  5. ListView Control mit MS-Access TreeView
  6. TreeView/ListView steuert Drag-Drop-Ereignisse