sql >> Databasteknik >  >> RDS >> Access

ListView Control Drag Drop Events Hantering

Introduktion.

Vi är bekanta med Dra och släpp-operationerna på TreeView Control, i Ms-Access som omarrangerar noder. Alla basposter för Treeview-kontrollnoderna kommer från en enda åtkomsttabell. Vi uppdaterar alltid källnodens förälder-ID fältvärde, med målnodens ID-värde på samma tabellpost, för att ändra positionen på TreeView-kontrollen. Posterna flyttas inte fysiskt någonstans.

Här, med tillägget av ListView Control tillsammans med TreeView Control, planerar vi att arbeta med två olika åtkomsttabeller.

  1. lvCategory – Kategorikod och beskrivning.
  2. lvProducts – Categorywise Products.

På så sätt är det lättare att förstå sambandet mellan de båda tabellerna. Vilka ändringar vi måste göra och var, när en produktartikel (ListView-objekt) flyttas från en kategori till en annan på TreeView-kontrollen.

lvCategory Access Table har 20 poster för TreeView-noderna och lvProducts Tabellen har 45 för ListView Control. En eller flera poster i tabellen Produkter är direkt relaterade till en produktkategori i kategoritabellen. Relationen mellan dem har uppdaterats med fältvärdet för kategori-ID (CID) på produkttabellens förälder-ID fältet så att ändringen av produktens kategori återspeglas omedelbart på ListView Control.

Demodatatabellen togs från Microsoft Access Sample Database Northwind.accdb och delades upp i två delar.

Baserat på ParentID Field Value, för lvProduct-poster, kan vi filtrera och lista alla relaterade produktartiklar i ListView-kontrollen när en kategorinod väljs i TreeView-kontrollen.

Ämnen vi har behandlat hittills.

Följande är huvudämnena i TreeView , Bildlista , ImageCombo, och ListView Kontroller, vi har täckt hittills i MS-Access:

  1. Microsoft TreeView Control Tutorial
  2. Skapa åtkomstmeny med TreeView-kontroll
  3. Tilldela bilder till TreeView-kontroll
  4. Tilldela bilder till TreeView Control-2
  5. TreeView Control Markera Lägg till Ta bort noder
  6. TreeView ImageCombo rullgardinsmeny
  7. Arrangera om TreeView-noder genom att dra och släppa
  8. ListView-kontroll med MS-Access TreeView

ListView Drag-Drop Task.

När det gäller ListViews Dra och släpp-operation är det en enkel övning som jämför samma metod enbart inom TreeView-kontrollen. Eftersom Drag Drop-åtgärden involverar både TreeView- och ListView-kontroller använder vi samma TreeView0_OLEDragDrop()-händelseprocedur med en enkel VBA-kod.

Produktobjekten som listas i ListView-kontrollen tillhör den aktuella kategoriposten som valts i TreeView-kontrollen.

Användaren väljer en specifik produktpost från ListView-kontrollen, om han/hon tror att den tillhör en annan kategoriartikel, dra och släpp den på målkategoriobjektet på TreeViewCcontrol.

Den flyttade ListView-produkten kommer att läggas till i listan över artiklar som tillhör den ändrade kategorin. Produktpostens ParentID-fältvärde uppdateras med målkategoripost-ID (CID-värde).

Det är bara en enkelriktad åtgärd, flytta alltid ListView-objektet från en kategori och släpp det på en annan kategorinod på TreeView-kontrollen.

ListView dra-släpp-demon Åtkomstformulär frmListViewDrag’ s testkörning Skärmbilden ges nedan:

På bilden ovan visas Drycker Kategori på trädvyn har valts. Produkterna som tillhör kategorin Drycker har listats i ListView Control.

Designvyn för ovanstående formulär:

Listan över kontrollnamn på formuläret är enligt nedan:

  1. TreeView-kontroll:TreeView0
  2. ListView Control:ListView0
  3. ImageList Control:ImageList3
  4. Kommandoknapp:cmdClose

VBA-koden på frmListViewDrag s klassmodul:

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

De välbekanta VBA-kodsegmenten.

I Form_Load() Händelseprocedur, vi initierar TreeVew, ListView, ImageList-kontrollerna. Det skapar kolumnrubriker av ListView Control, innan du fyller i listobjekt i Listview-kontrollen. I slutet av denna rutin anropar vi subrutinen LoadTreeView().

LoadTreeView() subrutinen fyller i produktens kategorinoder på TreeView-kontrollen, med posterna från lvCategory Tabell. Att ladda noder på TreeView-kontrollen är en process i två steg. Varför är det så, snarare än att göra det på en gång? Denna aspekt har förklarats i detalj på en tidigare sida, den 7:e länken på listan med länkar ge ovan om du vill gå igenom den. Att upprepa dem alla här kanske inte är lämpligt.

I slutet av ovanstående subrutin, LoadListView() subrutinen har anropats med den första kategoripostens CID-värde 1 som parameter.

Värdet 1 i fältet Product Records with ParentID har filtrerats och listats på ListView Control. Denna procedur förklarades i detalj i förra veckans inlägg, den 8:e punkten, bland listan över länkar ovan.

The Drag-Drop Action Subroutines.

Följande subrutiner kopplade till Dra och släpp-åtgärden kommer att köras automatiskt i den ordning de presenteras nedan:

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

De första och sista subrutinerna initierar de involverade noderna och återställer deras status i slutet respektive.

Den andra, OLEDragOver()-underrutinen fungerar som MouseMove Event Procedure och spårar musens rörelse under drag-släpp-operationen. Den markerar NodeTexten när musen är över en Nod och spårar dess bana tills vänster musknapp släpps.

Enbart Procedurkoden för TreeView0_OLEDragDrop() listas nedan.

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

Drag-släpp-åtgärden steg för steg.

TreeView0_OLEDragDrop()-proceduren körs omedelbart efter att vänster musknapp har släppts för att slutföra Drop-åtgärden. I början av koden har den aktiva och Target TreeView Nodes referenser sparats i tv_nodSource och tv_nodTarget objekt Variabler respektive.

Därefter utför vi en kontroll, om ListItem har släppts på en giltig TreeView-nod eller inte. Om det släpps på samma källkategorinod eller på ett tomt område på TreeView-kontrollen är dessa drag inte giltiga. Om den har släppts i ett tomt område i TreeView-kontrollen är tv_nodTarget objektvariabel kommer att innehålla värdet Ingenting. I så fall är det visar ett meddelande och avslutar programmet.

Därefter sparas nyckelvärdena för TreeView-källan och målnoden i två strängvariabler. Om båda nycklarna är desamma dras och släpps ListItem på sin egen överordnade nod (kategorinod) på TreeView-kontrollen. Programexekveringen avbryts från att fortsätta.

Om båda nycklarna är olika är det dags att uppdatera ändringen på produktpostens förälder-ID med målkategoripostens CID Koda och uppdatera ListView-objekten.

Det valda listobjektets nyckelvärde (PID fältvärde) har sparats i strListItemKey Strängvariabel.

Kategoripostens faktiska CID fältvärdet har extraherats från målnoden genom att ta bort prefixets teckenvärde X och sparats i variabeln vCatID . Detta är värdet som vi kommer att uppdatera i produktpostens ParentID-fält, för att placera ListItem under den nya kategorin.

På liknande sätt extraherades och sparades det valda listobjektets produkts nyckel-PID-värde i variabel lngPID . Detta har använts som kriterium för att filtrera och välja just den produktposten för uppdatering av ParentID-fältet med vCatID .

En UPPDATERING Query SQL har skapats för att filtrera posten med lngPID Koda som kriterier, för att filtrera produktposten och för att uppdatera vCatID Värde i P arentID fältet.

Execute metoden för Currentdb har anropats med SQL och uppdaterar ändringen.

Höjdpunkten för noden har återställts till källnoden.

Därefter har subrutinen TreeView0_NodeClick() anropats med tv_nodSource som en parameter för att återspegla ändringen på ListView Control.

Stäng Knappklick stänger formuläret.

Ladda ner demodatabas.

Du kan ladda ner demodatabasen, provköra och studera VBA-koden.


ÖNSKAR DIG ETT GOTT NYTT ÅR.

MS-ACCESS HANTERING AV HÄNDELSER

  1. Med Events MS-Access Class Module
  2. Med evenemang och definiera dina egna evenemang
  3. Textrutafliken Withevents Combo List
  4. Åtkomst till formulärkontrollarrayer och händelse
  5. Åtkomst till Form Control Arrays And Event-2
  6. Åtkomst till Form Control Arrays And Event-3
  7. Med händelser i klassmodul för underformulär
  8. Med händelser i klassmodul och data
  9. Med händelser och åtkomstrapport händelsesink
  10. Med händelser och rapportradsdöljning
  11. Med händelser och rapportlinjemarkering
  12. Med händelser Texbox och kommandoknapp
  13. Kommandoknapp för Withevents Textbox
  14. Med händelser och alla formulärkontrolltyper



  1. PostgreSQL:FEL:42601:en kolumndefinitionslista krävs för funktioner som returnerar post

  2. Hur använder man RETURNING med ON CONFLICT i PostgreSQL?

  3. Använd sammansatt primärnyckel som främmande nyckel

  4. Hur man säkerhetskopierar och återställer (exportera och importerar) MySQL-databaser