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

Handhabung von Drag-Drop-Ereignissen im ListView-Steuerelement

Einführung.

Wir sind vertraut mit den Drag-and-Drop-Operationen auf TreeView Control, in Ms-Access, das Knoten neu anordnet. Alle Basisdatensätze für die Treeview-Steuerknoten stammen aus einer einzigen Zugriffstabelle. Wir aktualisieren immer die ParentID des Quellknotens Feldwert mit dem ID-Wert des Zielknotens im selben Tabellendatensatz, um die Positionsänderung im TreeView-Steuerelement vorzunehmen. Die Aufzeichnungen werden nirgendwo physisch verschoben.

Hier planen wir mit der Hinzufügung des ListView-Steuerelements zusammen mit dem TreeView-Steuerelement, mit zwei verschiedenen Zugriffstabellen zu arbeiten.

  1. lvCategory – Kategoriecode und -beschreibung.
  2. lvProducts – Kategorieweise Produkte.

Auf diese Weise ist es einfacher, die Beziehung zwischen den beiden Tabellen zu verstehen. Welche Änderungen wir wo vornehmen müssen, wenn ein Produktelement (ListView-Element) im TreeView-Steuerelement von einer Kategorie in die andere verschoben wird.

Die lvCategory Die Access-Tabelle enthält 20 Datensätze für die TreeView-Knoten und die lvProducts Tabelle hat 45 für das ListView-Steuerelement. Ein oder mehrere Datensätze in der Produkttabelle stehen in direktem Zusammenhang mit einer Produktkategorie in der Kategorietabelle. Die Beziehung zwischen ihnen wurde mit dem Feldwert der Kategorie-ID (CID) in der ParentID der Produkttabelle aktualisiert Feld, sodass sich die Änderung der Kategorie des Produkts sofort im ListView-Steuerelement widerspiegelt.

Die Demodatentabelle wurde der Microsoft Access-Beispieldatenbank "Nordwind.accdb" entnommen und in zwei Teile geteilt.

Basierend auf dem ParentID-Feldwert von lvProduct-Datensätzen können wir alle zugehörigen Produktelemente im ListView-Steuerelement filtern und auflisten, wenn ein Kategorieknoten im TreeView-Steuerelement ausgewählt wird.

Themen, die wir bisher behandelt haben.

Im Folgenden finden Sie die Hauptthemen zu TreeView , Bildliste , Bildkombination, und ListView Steuerelemente, die wir bisher in MS-Access behandelt haben:

  1. Tutorial für das Microsoft TreeView-Steuerelement
  2. Zugriffsmenü mit TreeView-Steuerelement erstellen
  3. Bilder dem TreeView-Steuerelement zuweisen
  4. Zuweisen von Bildern zu TreeView Control-2
  5. TreeView Control-Häkchen hinzufügen Knoten löschen
  6. TreeView ImageCombo-Dropdown-Zugriffsmenü
  7. TreeView-Knoten per Drag-and-Drop neu anordnen
  8. ListView Control mit MS-Access TreeView

Die ListView-Drag-Drop-Aufgabe.

In Bezug auf die Drag-and-Drop-Operation von ListView ist es eine einfache Übung, die gleiche Methode nur innerhalb des TreeView-Steuerelements zu vergleichen. Da die Drag-Drop-Aktion sowohl TreeView- als auch ListView-Steuerelemente umfasst, verwenden wir dieselbe TreeView0_OLEDragDrop()-Ereignisprozedur mit einfachem VBA-Code.

Die im ListView-Steuerelement aufgelisteten Produktelemente gehören zum aktuellen Kategorieelement, das im TreeView-Steuerelement ausgewählt ist.

Der Benutzer wählt ein bestimmtes Produktelement aus dem ListView-Steuerelement aus, wenn er/sie glaubt, dass es zu einem anderen Kategorieelement gehört, und zieht es dann per Drag &Drop auf das Zielkategorieelement auf dem TreeViewC-Steuerelement.

Das verschobene ListView-Produktelement wird der Liste der Elemente hinzugefügt, die zur geänderten Kategorie gehören. Der ParentID-Feldwert des Produktdatensatzes wird mit der Datensatz-ID der Zielkategorie (CID-Wert) aktualisiert.

Es ist nur eine unidirektionale Aktion, verschieben Sie das ListView-Element immer aus einer Kategorie und legen Sie es auf einem anderen Kategorieknoten im TreeView-Steuerelement ab.

Das ListView-Drag-Drop-Demo-Zugriffsformular frmListViewDrag’ s Probelauf Bildschirmabbildung ist unten angegeben:

Im obigen Bild die Getränke Die Kategorie in der Baumansicht wurde ausgewählt. Die Produkte, die zur Kategorie Getränke gehören, wurden im ListView Control aufgelistet.

Die Entwurfsansicht des obigen Formulars:

Die Liste der Kontrollnamen auf dem Formular ist wie folgt:

  1. TreeView-Steuerelement:TreeView0
  2. ListView-Steuerelement:ListView0
  3. ImageList Control:ImageList3
  4. Befehlsschaltfläche:cmdClose

Der VBA-Code auf dem frmListViewDrag Klassenmodul von :

Option Compare Database
Option Explicit

Dim tv As MSComctlLib.TreeView
Dim lvList As MSComctlLib.ListView
Dim imgList As MSComctlLib.ImageList
Const Prfx As String = "X"

Private Sub Form_Load()
Dim db As DAO.Database
Dim tbldef As TableDef

    Set tv = Me.TreeView0.Object
    tv.Nodes.Clear
    
    Set imgList = Me.ImageList3.Object
    
With tv
    .Font.Size = 9
    .Font.Name = "Verdana"
    .ImageList = imgList 'assign preloaded imagelist control
 End With
    
    Set lvList = Me.ListView0.Object
    lvList.ColumnHeaders.Clear
    lvList.ListItems.Clear
    lvList.Icons = imgList
    
    Set db = CurrentDb
    Set tbldef = db.TableDefs("lvProducts")
    
    'Initialize ListView & Column Headers Property Values
     With lvList
        .ColumnHeaderIcons = imgList
        .Font.Size = 9
        .Font.Name = "Verdana"
        .Font.Bold = False
        
        'ColumnHeaders.Add() Syntax:
        'lvList.ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon
        'Alignment: 0 - Left, 1 - Right, 2 - Center
        .ColumnHeaders.Add 1, , tbldef.Fields(1).Name, 2600, 0, 5
        .ColumnHeaders.Add 2, , tbldef.Fields(3).Name, 2600, 0, 5
        .ColumnHeaders.Add 3, , tbldef.Fields(4).Name, 1440, 1, 5
    End With
    
    Set db = Nothing
    Set tbldef = Nothing

    
   LoadTreeView 'Create TreeView Nodes

End Sub

Private Sub LoadTreeView()
    Dim Nod As MSComctlLib.Node
    Dim firstCatID As Long
    Dim strCategory As String
    Dim strCatKey As String
    Dim strBelongsTo As String
    Dim strSQL As String
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    
    'Initialize treeview nodes
     tv.Nodes.Clear
     
    'Initialize Listview nodes
    While lvList.ListItems.Count > 0
          lvList.ListItems.Remove (1)
    Wend
    
    strSQL = "SELECT lvCategory.CID, lvCategory.Category, "
    strSQL = strSQL & "lvcategory.BelongsTo FROM lvCategory ORDER BY lvCategory.CID;"
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot)
    
    If Not rst.BOF And Not rst.EOF Then
        rst.MoveFirst
        firstCatID = rst!CID
    Else
        Exit Sub
    End If
    ' Populate all Records as Rootlevel Nodes
    Do While Not rst.BOF And Not rst.EOF
            strCatKey = Prfx & CStr(rst!CID)
            strCategory = rst!Category
            
            Set Nod = tv.Nodes.Add(, , strCatKey, strCategory, 1, 2)
            Nod.Tag = rst!CID
        rst.MoveNext
    Loop
    
    'In the second pass of the the same set of records
    'Move Child Nodes under their Parent Nodes
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
        strBelongsTo = Nz(rst!BelongsTo, "")
        If Len(strBelongsTo) > 0 Then
            strCatKey = Prfx & CStr(rst!CID)
            strBelongsTo = Prfx & strBelongsTo
            strCategory = rst!Category
            
            Set tv.Nodes.Item(strCatKey).Parent = tv.Nodes.Item(strBelongsTo)
        End If
        rst.MoveNext
    Loop
    rst.Close
    
    ' Populate ListView Control with Product details
    ' of the first Category Item
    LoadListView firstCatID
    
End Sub


Private Sub LoadListView(ByVal CatID)
    Dim strProduct As String
    Dim strPKey As String
    Dim intcount As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim strSQL As String
    
    ' Initialize ListView Control
    While lvList.ListItems.Count > 0
        lvList.ListItems.Remove (1)
    Wend
   
     strSQL = "SELECT lvProducts.* FROM lvProducts "
     strSQL = strSQL & "WHERE (lvProducts.ParentID = " & CatID & ") "
     strSQL = strSQL & "ORDER BY lvProducts.[Product Name];"
    
    'Open filtered Products List for selected category
    Set db = CurrentDb
    Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot)
    
    Do While Not rst.BOF And Not rst.EOF
        intcount = intcount + 1
        strProduct = rst![Product Name]
        strPKey = Prfx & CStr(rst!PID)
        
        'List Item Add() Syntax:
        'lvList.ListItems.Add Index,Key,Text,Icon,SmallIcon
        Set tmpLItem = lvList.ListItems.Add(, strPKey, strProduct, , 3) 'first column
            lvList.ForeColor = vbBlue
            
            'List second column sub-item Syntax:
            'tmpLItem.ListSubItems.Add Column - Index, Key, Text, ReportIcon, ToolTipText
            tmpLItem.ListSubItems.Add 1, strPKey & CStr(intcount), Nz(rst![Quantity Per Unit], ""), 6
            
            'List third column sub-item
            tmpLItem.ListSubItems.Add 2, strPKey & CStr(intcount + 1), Format(rst![list Price], "0.00"), 6, "In Local Currency."
        rst.MoveNext
    Loop
    
    Set db = Nothing
    Set rst = Nothing
    
    If intcount > 0 Then lvList.ListItems(1).Selected = True
    
End Sub

Private Sub TreeView0_NodeClick(ByVal Node As Object)
Dim Cat_ID As String
Cat_ID = Node.Tag

LoadListView Cat_ID

End Sub

Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long)
    Set tv.SelectedItem = Nothing
End Sub

Private Sub TreeView0_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer)
On Error GoTo TreeView0_OLEDragOver_Err

    Dim nodSelected As MSComctlLib.Node
    Dim nodOver As MSComctlLib.Node
    
    If tv.SelectedItem Is Nothing Then
        'Select a node if one is not selected
        Set nodSelected = tv.HitTest(X, Y)
        If Not nodSelected Is Nothing Then
            nodSelected.Selected = True
        End If
    Else
        If tv.HitTest(X, Y) Is Nothing Then
        'do nothing
        Else
            'Highlight the node the mouse is over
            Set nodOver = tv.HitTest(X, Y)
            Set tv.DropHighlight = nodOver
        End If
    End If
    
TreeView0_OLEDragOver_Exit:
Exit Sub

TreeView0_OLEDragOver_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragOver()"
Resume TreeView0_OLEDragOver_Exit
End Sub


Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)

    Dim tv_nodSource As Node
    Dim tv_nodTarget As Node
    
    Dim strtv_ParentKey As String
    Dim strtv_TargetKey As String
    Dim strListItemKey As String
    Dim strSQL As String
    
    Dim vCatID As Long
    Dim lngPID As Long
    
    On Error GoTo TreeView0_OLEDragDrop_Err
    
    'Get the source/destination Nodes
    Set tv_nodSource = tv.SelectedItem
    Set tv_nodTarget = tv.HitTest(X, Y)
    
        If Not tv_nodTarget Is Nothing Then
            strtv_ParentKey = tv_nodSource.Key
            strtv_TargetKey = tv_nodTarget.Key
                
            If strtv_ParentKey = strtv_TargetKey Then Exit Sub

            'Extract ListItem Key
            strListItemKey = lvList.SelectedItem.Key
                
            'extract Category Record CID Value
            'and ListItem Product ID Key
            vCatID = Val(Mid(tv_nodTarget.Key, 2))
            lngPID = Val(Mid(strListItemKey, 2))
    
            'UPDATE lvProducts Table
            strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _
            " WHERE PID = " & lngPID
             
            CurrentDb.Execute strSQL, dbFailOnError
                
            Set tv.DropHighlight = Nothing
            tv_nodSource.Selected = True
                
            'Rebuild ListView Nodes
            TreeView0_NodeClick tv_nodSource
                
        Else ' Invalid Target location
            MsgBox "The destination is invalid!", vbInformation
        End If
    
TreeView0_OLEDragDrop_Exit:
Exit Sub

TreeView0_OLEDragDrop_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()"
Resume TreeView0_OLEDragDrop_Exit
End Sub

Private Sub TreeView0_OLECompleteDrag(Effect As Long)
    Set tv.DropHighlight = Nothing
End Sub

Private Sub cmdClose_Click()
    DoCmd.Close
End Sub

Die vertrauten VBA-Codesegmente.

Im Form_Load() Ereignisprozedur initialisieren wir die TreeVew-, ListView- und ImageList-Steuerelemente. Es erstellt die ColumnHeadings des ListView-Steuerelements, bevor Listenelemente im Listview-Steuerelement ausgefüllt werden. Am Ende dieser Routine rufen wir die Subroutine LoadTreeView() auf.

Das LoadTreeView() Die Unterroutine füllt die Kategorieknoten der Produkte im TreeView-Steuerelement mit den Datensätzen aus der lvCategory Tisch. Das Laden von Knoten im TreeView-Steuerelement ist ein zweistufiger Prozess. Warum ist es so, anstatt es auf einmal zu tun? Dieser Aspekt wurde auf einer früheren Seite, dem 7. Link, ausführlich erläutert auf der Liste der oben angegebenen Links, wenn Sie sie durchgehen möchten. Sie alle hier zu wiederholen, ist möglicherweise nicht angemessen.

Am Ende der obigen Subroutine wird die LoadListView() Die Unterroutine wurde mit dem CID-Wert 1 des ersten Kategoriedatensatzes aufgerufen als Parameter.

Die Produktdatensätze mit dem ParentID-Feldwert 1 wurden gefiltert und im ListView-Steuerelement aufgelistet. Dieses Verfahren wurde im Post der letzten Woche, dem 8. Punkt, unter der oben angegebenen Linkliste ausführlich erläutert.

Die Subroutinen für Drag-Drop-Aktionen.

Die folgenden Subroutinen, die der Drag-and-Drop-Aktion zugeordnet sind, werden automatisch in der unten angegebenen Reihenfolge ausgeführt:

  1. TreeView0_OLEStartDrag()
  2. TreeView0_OLEDragOver()
  3. TreeView0_OLEDragDrop()
  4. TreeView0_OLECompleteDrag()

Das erste und das letzte Unterprogramm initialisieren die beteiligten Knoten und setzen am Ende jeweils ihren Status zurück.

Die zweite Subroutine OLEDragOver() funktioniert wie die MouseMove-Ereignisprozedur und verfolgt die Bewegung der Maus während des Drag-Drop-Vorgangs. Es hebt den Knotentext hervor, wenn sich die Maus über einem Knoten befindet, und verfolgt seine Flugbahn, bis die linke Maustaste losgelassen wird.

Der Prozedurcode TreeView0_OLEDragDrop() allein ist unten aufgeführt.

Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)

    Dim tv_nodSource As Node
    Dim tv_nodTarget As Node
    
    Dim strtv_ParentKey As String
    Dim strtv_TargetKey As String
    Dim strListItemKey As String
    Dim strSQL As String
    
    Dim vCatID As Long
    Dim lngPID As Long
    
    On Error GoTo TreeView0_OLEDragDrop_Err
    
    'Get the source/destination Nodes
    Set tv_nodSource = tv.SelectedItem
    Set tv_nodTarget = tv.HitTest(X, Y)
    
        If Not tv_nodTarget Is Nothing Then
            strtv_ParentKey = tv_nodSource.Key
            strtv_TargetKey = tv_nodTarget.Key
                
            If strtv_ParentKey = strtv_TargetKey Then Exit Sub

            'Extract ListItem Key
            strListItemKey = lvList.SelectedItem.Key
                
            'extract Category Record CID Value
            'and ListItem Product ID Key
            vCatID = Val(Mid(tv_nodTarget.Key, 2))
            lngPID = Val(Mid(strListItemKey, 2))
    
            'UPDATE lvProducts Table
            strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _
            " WHERE PID = " & lngPID
             
            CurrentDb.Execute strSQL, dbFailOnError
                
            Set tv.DropHighlight = Nothing
            tv_nodSource.Selected = True
                
            'Rebuild ListView Nodes
            TreeView0_NodeClick tv_nodSource
                
        Else ' Invalid Target location
            MsgBox "The destination is invalid!", vbInformation
        End If
    
TreeView0_OLEDragDrop_Exit:
Exit Sub

TreeView0_OLEDragDrop_Err:
MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()"
Resume TreeView0_OLEDragDrop_Exit
End Sub

Die Drag-Drop-Aktion Schritt für Schritt.

Die TreeView0_OLEDragDrop()-Prozedur wird sofort ausgeführt, nachdem die linke Maustaste losgelassen wurde, um die Drop-Aktion abzuschließen. Zu Beginn des Codes wurden der aktive und die Referenzen des Target TreeView-Knotens in tv_nodSource gespeichert und tv_nodTarget Objektvariablen bzw.

Als nächstes führen wir eine Überprüfung durch, ob das ListItem auf einem gültigen TreeView-Knoten abgelegt wurde oder nicht. Wenn es auf demselben Quellkategorieknoten oder auf einem leeren Bereich des TreeView-Steuerelements abgelegt wird, sind diese Verschiebungen nicht gültig. Wenn es in einem leeren Bereich des TreeView-Steuerelements abgelegt wurde, dann das tv_nodTarget Die Objektvariable enthält den Wert Nothing. In diesem Fall zeigt eine Meldung an und beendet das Programm.

Als Nächstes werden die Schlüsselwerte der TreeView-Quelle und des Zielknotens in zwei String-Variablen gespeichert. Wenn beide Schlüssel identisch sind, wird das ListItem per Drag &Drop auf seinen eigenen übergeordneten Knoten (Kategorieknoten) im TreeView-Steuerelement gezogen. Die Programmausführung wird abgebrochen, um weiter fortzufahren.

Wenn beide Schlüssel unterschiedlich sind, ist es an der Zeit, die Änderung an der ParentID des Produktdatensatzes zu aktualisieren mit der CID des Zielkategorie-Datensatzes Code, und aktualisieren Sie die ListView-Elemente.

Der Schlüsselwert des ausgewählten ListItems (PID Feldwert) wurde im strListItemKey gespeichert String-Variable.

Die tatsächliche CID des Kategoriedatensatzes Der Feldwert wurde aus dem Zielknoten extrahiert, indem der Präfixzeichenwert X entfernt und in der Variablen vCatID gespeichert wurde . Dies ist der Wert, den wir im ParentID-Feld des Produktdatensatzes aktualisieren, um das ListItem unter der neuen Kategorie zu platzieren.

In ähnlicher Weise wird der Schlüssel-PID-Wert des Produkts des ausgewählten Listenelements extrahiert und in der Variablen lngPID gespeichert . Dies wurde als Kriterium verwendet, um diesen bestimmten Produktdatensatz zu filtern und auszuwählen, um das ParentID-Feld mit vCatID zu aktualisieren .

Ein UPDATE Abfrage-SQL wurde erstellt, um den Datensatz unter Verwendung der lngPID zu filtern Code als Kriterien, um den Produktdatensatz zu filtern und die vCatID zu aktualisieren Wert im P arentID Feld.

Die Ausführen Methode der Currentdb wurde mit dem SQL aufgerufen und aktualisiert die Änderung.

Die Hervorhebung des Knotens wurde auf den Quellknoten zurückgesetzt.

Als nächstes wurde die Subroutine TreeView0_NodeClick() mit der tv_nodSource aufgerufen als Parameter, um die Änderung am ListView-Steuerelement widerzuspiegeln.

Das Schließen Klicken Sie auf die Schaltfläche, um das Formular zu schließen.

Demo-Datenbank herunterladen.

Sie können die Demo-Datenbank herunterladen, Testläufe durchführen und den VBA-Code studieren.


WÜNSCHE IHNEN EIN SEHR GLÜCKLICHES NEUES JAHR.

MS-ACCESS-EREIGNISBEHANDLUNG

  1. Withevents MS-Access-Klassenmodul
  2. Withevents und Definieren eigener Events
  3. Textfeld-Registerkarte „Withevents Combo List“
  4. Zugriff auf Formularsteuerungs-Arrays und -Ereignisse
  5. Zugriff auf Form Control Arrays und Event-2
  6. Zugriff auf Form Control Arrays und Event-3
  7. Withevents im Klassenmodul für Unterformular
  8. Withevents in Klassenmodul und Daten
  9. Withevents and Access Report-Ereignissenke
  10. Mit Ereignissen und Ausblenden von Berichtszeilen
  11. Mit Ereignissen und Hervorhebung von Berichtszeilen
  12. Mit Ereignistextfeld und Befehlsschaltfläche
  13. Withevents-Textfeld-Befehlsschaltfläche
  14. Withevents und All Form Control Types