Access
 sql >> Base de Dados >  >> RDS >> Access

Manipulação de eventos de arrastar e soltar de controle ListView

Introdução.


Estamos familiarizados com as operações de arrastar e soltar no controle TreeView, no Ms-Access que reorganiza Nodes. Todos os registros de base para os nós de controle Treeview vêm de uma única tabela de acesso. Sempre atualizamos o ParentID do nó de origem valor do campo, com o Valor ID do Nó de Destino no mesmo registro da Tabela, para fazer a mudança de posição no Controle TreeView. Os registros não são movidos fisicamente para nenhum lugar.

Aqui, com a adição de ListView Control junto com TreeView Control, planejamos trabalhar com duas tabelas de acesso diferentes.
  1. lvCategory – Código e descrição da categoria.
  2. lvProducts – Produtos Categorywise.

Assim fica mais fácil entender a relação entre as duas Tabelas. Quais alterações temos que fazer e onde, quando um item de produto (item ListView) se move de uma categoria para outra no controle TreeView.

A lvCategory A tabela de acesso tem 20 registros para os nós TreeView e os lvProducts A tabela tem 45 para o controle ListView. Um ou mais registros na tabela Produtos estão diretamente relacionados a uma categoria de produto na Tabela Categoria. A relação entre eles foi atualizada com o valor do campo ID da categoria (CID) no ParentID da Tabela de produtos campo para que a mudança de categoria do produto reflita imediatamente no controle ListView.

A tabela de dados de demonstração foi retirada do banco de dados de exemplo do Microsoft Access Northwind.accdb e dividida em duas partes.

Com base no valor do campo ParentID, dos registros lvProduct, podemos filtrar e listar todos os itens de produtos relacionados no controle ListView, quando um nó de categoria é selecionado no controle TreeView.

Tópicos que cobrimos até agora.


A seguir estão os principais tópicos no TreeView , Lista de imagens , ImageCombo, e ListView Controles, que cobrimos até agora no MS-Access:
  1. Tutorial de controle do Microsoft TreeView
  2. Criando menu de acesso com controle TreeView
  3. Atribuindo imagens ao controle TreeView
  4. Atribuindo imagens ao TreeView Control-2
  5. Marque de seleção de controle do TreeView Adicionar nós de exclusão
  6. Menu de acesso suspenso do TreeView ImageCombo
  7. Reorganize os nós do TreeView arrastando e soltando
  8. Controle de ListView com MS-Access TreeView

A tarefa de arrastar e soltar ListView.


No que diz respeito à operação de arrastar e soltar do ListView, é um exercício simples comparando o mesmo método dentro do controle TreeView sozinho. Como a ação Arrastar Soltar envolve os controles TreeView e ListView, usamos o mesmo procedimento de evento TreeView0_OLEDragDrop() com algum código VBA simples.

Os itens de produto listados no controle ListView pertencem ao item de categoria atual selecionado no controle TreeView.

O usuário seleciona um determinado item de produto do controle ListView, se ele acha que pertence a um item de categoria diferente, então arraste e solte no item de categoria de destino no TreeViewCcontrol.

O Item do Produto ListView movido será adicionado à lista de itens que pertencem à Categoria alterada. O valor do campo ParentID do registro do produto é atualizado com o ID do registro de categoria de destino (valor CID).

É apenas uma ação unidirecional, sempre mova o item ListView de uma categoria e solte-o em um nó de categoria diferente no controle TreeView.

O formulário de acesso de demonstração de arrastar e soltar ListView frmListViewDrag' A imagem da tela de execução de teste é fornecida abaixo:

Na imagem acima, as Bebidas A categoria no TreeView foi selecionada. Os produtos pertencentes à categoria Bebidas foram listados no Controle ListView.

A visualização de design do formulário acima:

A lista de nomes de controle no formulário é a seguinte:
  1. Controle TreeView:TreeView0
  2. Controle ListView:ListView0
  3. Controle ImageList:ImageList3
  4. Botão de comando:cmdFechar

O código VBA no frmListViewDrag Módulo de classe do :
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

Os segmentos de código VBA familiares.

No Form_Load() Event Procedure, inicializamos os controles TreeVew, ListView, ImageList. Ele cria os ColumnHeadings do controle ListView, antes de preencher itens de lista no controle Listview. Ao final desta rotina, chamamos a sub-rotina LoadTreeView().

O LoadTreeView() sub-rotina preenche os nós de categoria dos produtos no controle TreeView, com os registros da lvCategory Tabela. O carregamento de nós no controle TreeView é um processo de duas etapas. Por que é assim, em vez de fazê-lo de uma só vez? Este aspecto foi explicado em detalhes em uma página anterior, o 7º link na lista de links acima, se você quiser passar por isso. Repetir todos eles aqui pode não ser apropriado.

No final da sub-rotina acima, o LoadListView() a sub-rotina foi chamada com o valor CID do primeiro registro de categoria 1 como parâmetro.

Os registros do produto com o valor do campo ParentID 1 foram filtrados e listados no controle ListView. Este procedimento foi explicado detalhadamente no post da semana passada, o 8º item, dentre a Lista de Links dada acima.

As sub-rotinas de ação de arrastar e soltar.


As seguintes Sub-rotinas associadas à ação Arrastar e Soltar serão executadas automaticamente na ordem em que são apresentadas abaixo:
  1. TreeView0_OLEStartDrag()
  2. TreeView0_OLEDragOver()
  3. TreeView0_OLEDragDrop()
  4. TreeView0_OLECompleteDrag()

A primeira e a última Sub-rotinas inicializam os Nodes envolvidos e reiniciam seus status no final, respectivamente.

A segunda, a sub-rotina OLEDragOver() funciona como o MouseMove Event Procedure e acompanha o movimento do mouse durante a operação de arrastar e soltar. Ele destaca o NodeText quando o mouse está sobre um Node e rastreia sua trajetória até que o botão esquerdo do mouse seja liberado.

O código do procedimento TreeView0_OLEDragDrop() sozinho está listado abaixo.
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

A ação de arrastar e soltar passo a passo.


O procedimento TreeView0_OLEDragDrop() é executado imediatamente após o botão esquerdo do mouse ser liberado para concluir a ação de soltar. No início do código, as referências do nó TreeView ativo e de destino foram salvas em tv_nodSource e tv_nodTarget Variáveis ​​de objeto respectivamente.

Em seguida, realizamos uma verificação, se o ListItem foi descartado em um nó TreeView válido ou não. Se ele for solto no mesmo nó de categoria de origem ou em uma área vazia no controle TreeView, esses movimentos não serão válidos. Se ele foi solto em uma área vazia do TreeView Control, o tv_nodTarget variável de objeto conterá o valor Nada. Nesse caso, exibe uma mensagem e sai do Programa.

Em seguida, os valores-chave do nó de origem e de destino TreeView estão sendo salvos em duas variáveis ​​de string. Se ambas as chaves forem iguais, então o ListItem arrastou e soltou em seu próprio nó pai (nó de categoria) no controle TreeView. A execução do programa é abortada de prosseguir.

Se ambas as chaves forem diferentes, é hora de atualizar a alteração no ParentID do registro do produto campo, com o CID do registro de categoria de destino Code e atualize os itens ListView.

O valor da chave do ListItem selecionado (PID valor do campo) foi salvo no strListItemKey Variável de string.

O CID real do registro da categoria o valor do campo foi extraído do nó de destino, removendo o valor do caractere de prefixo X e salvo na variável vCatID . Este é o Valor que iremos atualizar no campo ParentID do Product Record, para colocar o ListItem na nova Category.

Da mesma forma, o valor PID da chave do produto do item de lista selecionado é extraído e salvo na variável lngPID . Isso foi usado como critério para filtrar e selecionar esse registro de produto específico para atualizar o campo ParentID com vCatID .

Uma ATUALIZAÇÃO A consulta SQL foi criada para filtrar o registro, usando o lngPID Codifique como critérios para filtrar o registro do produto e atualizar o vCatID Valor no P arentID campo.

O Executar método do Currentdb foi chamado com o SQL e atualiza a alteração.

O Destaque do Nó foi redefinido para o Nó de Origem.

Em seguida, a sub-rotina TreeView0_NodeClick() foi chamada com o tv_nodSource como um parâmetro para refletir a alteração no controle ListView.

O Fechar Clique no botão fechará o formulário.

Baixe o banco de dados de demonstração.


Você pode baixar o banco de dados Demo, fazer testes e estudar o código VBA.


DESEJAMOS UM FELIZ ANO NOVO.

TRATAMENTO DE EVENTOS MS-ACCESS

  1. Módulo de classe do MS-Access Withevents
  2. Com eventos e definindo seus próprios eventos
  3. Guia da caixa de texto da lista de combinação Withevents
  4. Matrizes e eventos de controle de formulário de acesso
  5. Matrizes de controle de formulário de acesso e evento-2
  6. Matrizes de controle de formulário de acesso e evento-3
  7. Módulo Withevents in Class para subformulário
  8. Com eventos no módulo de classe e dados
  9. Withevents e Access Report Event Sink
  10. Com eventos e ocultação de linha de relatório
  11. Withevents e destaque de linha de relatório
  12. Withevents Texbox e botão de comando
  13. Botão de comando da caixa de texto Withevents
  14. Com eventos e todos os tipos de controle de formulário