sql >> Base de Datos >  >> RDS >> Access

ListView Control Arrastrar Soltar Gestión de eventos

Introducción.

Estamos familiarizados con las operaciones de arrastrar y soltar en TreeView Control, en Ms-Access que reorganiza los nodos. Todos los registros base para los nodos de control Treeview provienen de una única tabla de acceso. Siempre actualizamos el ParentID del nodo de origen valor de campo, con el Valor de ID del Nodo de Destino en el mismo registro de la Tabla, para realizar el cambio de posición en el Control TreeView. Los registros no se mueven físicamente a ningún lado.

Aquí, con la adición de ListView Control junto con TreeView Control, planeamos trabajar con dos tablas de acceso diferentes.

  1. lvCategory:código de categoría y descripción.
  2. lvProducts:productos por categoría.

De esta forma es más fácil entender la relación entre ambas Tablas. Qué cambios tenemos que hacer y dónde, cuando un elemento de producto (elemento ListView) se mueve de una categoría a otra en el control TreeView.

La categoría lv Access Table tiene 20 registros para TreeView Nodes y lvProducts La tabla tiene 45 para el control ListView. Uno o más registros en la tabla Productos están directamente relacionados con una categoría de productos en la Tabla de categorías. La relación entre ellos se actualizó con el valor del campo Id. de categoría (CID) en el ParentID de la tabla de productos. campo para que el cambio de categoría del producto se refleje inmediatamente en el ListView Control.

La tabla de datos de demostración se tomó de Microsoft Access Sample Database Northwind.accdb y se dividió en dos partes.

Según el valor del campo ParentID, de los registros lvProduct, podríamos filtrar y enumerar todos los elementos de productos relacionados en el control ListView, cuando se selecciona un nodo de categoría en el control TreeView.

Temas que hemos cubierto hasta ahora.

Los siguientes son los temas principales en TreeView , Lista de imágenes , ImageCombo, y Vista de lista Controles que hemos cubierto hasta ahora en MS-Access:

  1. Tutorial de control TreeView de Microsoft
  2. Creación del menú de acceso con TreeView Control
  3. Asignación de imágenes al control TreeView
  4. Asignación de imágenes a TreeView Control-2
  5. Control de TreeView Marca de verificación Agregar Eliminar nodos
  6. Menú de acceso desplegable TreeView ImageCombo
  7. Reorganizar los nodos de TreeView arrastrando y soltando
  8. Control ListView con MS-Access TreeView

La tarea de arrastrar y soltar ListView.

En lo que respecta a la operación de arrastrar y soltar de ListView, es un ejercicio simple que compara el mismo método solo dentro del control TreeView. Dado que la acción Arrastrar y soltar involucra tanto los controles TreeView como ListView, usamos el mismo procedimiento de evento TreeView0_OLEDragDrop() con un código VBA simple.

Los elementos del producto enumerados en el control ListView pertenecen al elemento de categoría actual seleccionado en el control TreeView.

El usuario selecciona un elemento de producto en particular del control ListView, si cree que pertenece a un elemento de categoría diferente, luego arrástrelo y suéltelo en el elemento de categoría de destino en el control TreeViewC.

El elemento de producto ListView movido se agregará a la lista de elementos que pertenecen a la categoría modificada. El valor del campo ParentID del registro del producto se actualiza con el ID del registro de la categoría de destino (valor CID).

Es solo una acción unidireccional, siempre mueva el elemento ListView de una categoría y colóquelo en un nodo de categoría diferente en el control TreeView.

El formulario de acceso de demostración de arrastrar y soltar de ListView frmListViewDrag’ La imagen de la pantalla de ejecución de prueba se muestra a continuación:

En la Imagen de arriba, las Bebidas Se ha seleccionado la categoría en TreeView. Los productos pertenecientes a la categoría Bebidas han sido listados en el ListView Control.

La vista de diseño del formulario anterior:

La lista de nombres de control en el formulario es la siguiente:

  1. Control TreeView:TreeView0
  2. Control de vista de lista:Vista de lista0
  3. Control de lista de imágenes:ImageList3
  4. Botón de comando:cmdCerrar

El código VBA en frmListViewDrag Módulo de clase:

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

Los familiares segmentos de código VBA.

En el Form_Load() Procedimiento de evento, inicializamos los controles TreeVew, ListView, ImageList. Crea los Encabezados de columna del control ListView, antes de completar los elementos de la lista en el control Listview. Al final de esta rutina, llamamos a la subrutina LoadTreeView().

El LoadTreeView() subrutina rellena los nodos de categoría de los productos en el control TreeView, con los registros de lvCategory Mesa. La carga de nodos en el control TreeView es un proceso de dos pasos. ¿Por qué es así, en lugar de hacerlo de una vez? Este aspecto se ha explicado en detalle en una página anterior, el enlace 7 en la lista de enlaces que figuran arriba si desea revisarla. Repetirlos todos aquí puede no ser apropiado.

Al final de la subrutina anterior, LoadListView() se ha llamado a la subrutina con el valor CID del primer registro de categoría 1 como parámetro.

Los registros de productos con el valor del campo ParentID 1 han sido filtrados y listados en ListView Control. Este procedimiento fue explicado en detalle en la publicación de la semana pasada, el artículo 8, entre la Lista de Enlaces dada arriba.

Las subrutinas de acción de arrastrar y soltar.

Las siguientes subrutinas asociadas con la acción de arrastrar y soltar se ejecutarán automáticamente en el orden en que se presentan a continuación:

  1. Vista de árbol0_OLEStartDrag()
  2. TreeView0_OLEDragOver()
  3. Vista de árbol0_OLEDragDrop()
  4. TreeView0_OLECompleteDrag()

La primera y la última Subrutina inicializan los Nodos involucrados y restablecen su estado al final respectivamente.

La segunda, la subrutina OLEDragOver(), funciona como el procedimiento de evento MouseMove y rastrea el movimiento del mouse durante la operación de arrastrar y soltar. Resalta el NodeText cuando el mouse está sobre un Nodo y rastrea su trayectoria hasta que se suelta el botón izquierdo del mouse.

El código del procedimiento TreeView0_OLEDragDrop() solo se muestra a continuación.

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

La acción de arrastrar y soltar paso a paso.

El procedimiento TreeView0_OLEDragDrop() se ejecuta inmediatamente después de soltar el botón izquierdo del mouse para completar la acción de soltar. Al comienzo del código, las referencias activas y del Nodo TreeView de destino se han guardado en tv_nodSource y tv_nodTarget Objeto Variables respectivamente.

A continuación, realizamos una verificación, si ListItem se ha colocado en un nodo TreeView válido o no. Si se coloca en el mismo nodo de categoría de origen o en un área vacía en el control TreeView, estos movimientos no son válidos. Si se ha soltado en un área vacía del control TreeView, entonces tv_nodTarget La variable de objeto contendrá el valor Nada. En ese caso, muestra un mensaje y sale del programa.

A continuación, los valores clave del nodo de origen y de destino de TreeView se guardan en dos variables de cadena. Si ambas claves son iguales, ListItem se arrastra y suelta en su propio nodo principal (nodo de categoría) en el control TreeView. La ejecución del programa se cancela para continuar.

Si ambas claves son diferentes, entonces es hora de actualizar el cambio en el ParentID del registro de producto. campo, con el CID del registro de categoría objetivo Codifique y actualice los elementos de ListView.

El valor clave del ListItem seleccionado (PID valor de campo) se ha guardado en strListItemKey Variable de cadena.

El CID real del registro de categoría el valor del campo se ha extraído del nodo de destino, eliminando el valor del carácter del prefijo X y guardándolo en la variable vCatID . Este es el valor que actualizaremos en el campo ParentID del registro del producto para colocar el ListItem en la nueva categoría.

Del mismo modo, el valor de PID clave del producto del elemento de lista seleccionado se extrae y se guarda en la variable lngPID . Esto se ha utilizado como criterio para filtrar y seleccionar ese registro de Producto en particular para actualizar el campo ParentID con vCatID .

Una ACTUALIZACIÓN Se ha creado Query SQL para filtrar el registro, usando el lngPID Código como criterio, para filtrar el registro del producto y para actualizar el vCatID Valor en la P arentID campo.

Ejecutar método de Currentdb ha sido llamado con el SQL y actualiza el cambio.

El punto culminante del nodo se ha restablecido al nodo de origen.

A continuación, se ha llamado a la subrutina TreeView0_NodeClick() con tv_nodSource como parámetro para reflejar el cambio en ListView Control.

El Cerrar Hacer clic en el botón cerrará el formulario.

Descargar base de datos de demostración.

Puede descargar la base de datos de demostración, realizar pruebas y estudiar el código VBA.


LES DESEO UN MUY FELIZ AÑO NUEVO.

GESTIÓN DE EVENTOS DE MS-ACCESS

  1. Con eventos MS-Access Class Module
  2. Con eventos y definición de sus propios eventos
  3. Pestaña de cuadro de texto de lista combinada de eventos
  4. Acceso a arreglos de control de formularios y eventos
  5. Arrays de control de formulario de acceso y Event-2
  6. Arrays de control de formulario de acceso y Event-3
  7. Con eventos en el módulo de clase para subformulario
  8. Con eventos en Módulo de Clase y Datos
  9. Sumidero de eventos de informes de acceso y sin eventos
  10. Sin eventos y Ocultación de línea de informe
  11. Con eventos y resaltado de línea de informe
  12. Con cuadro de texto de eventos y botón de comando
  13. Botón de comando del cuadro de texto Withevents
  14. Con eventos y todos los tipos de control de formulario