Introducción.
Espero que haya encontrado útil el tutorial de la semana pasada sobre ImageCombo Control para sus proyectos de Microsoft Access. Con el control TreeView ImageCombo, pudimos crear un hermoso menú desplegable, con varias opciones, y acomodarlo en un pequeño espacio en el formulario.
Del mismo modo, en una sesión anterior, aprendimos cómo agregar nuevos nodos en una ubicación específica en la jerarquía de nodos o eliminar un nodo y agregar uno nuevo para reubicar un nodo en el Control de vista de árbol.
Este método solicita la creación de un nuevo registro en la tabla de origen para el nuevo nodo. O elimine un registro existente y cree uno nuevo para mover un nodo existente y hacerlo permanente. En cierto modo, con el uso de las funciones Agregar/Eliminar, podríamos agregar nuevos nodos o reorganizar los nodos existentes en el control TreeView. En lo que respecta a la reorganización de los nodos, tenemos una mejor manera de hacerlo, en lugar de eliminar los nodos y volver a crearlos. Arrastre el nodo desde su ubicación actual y suéltelo donde queremos que esté en el control TreeView. Esto es lo que vamos a aprender en este episodio
Este enfoque simple solo necesita actualizar el cambio del valor del campo ParentID de los registros relacionados, para que el cambio sea permanente.
Los temas tratados hasta ahora en sesiones anteriores.
- Tutorial de control TreeView de Microsoft
- Creación del menú de acceso con TreeView Control
- Asignación de imágenes al control TreeView
- Asignación de imágenes a TreeView Control-2
- Control de TreeView Marca de verificación Agregar Eliminar nodos
- Menú de acceso desplegable TreeView ImageCombo
Sin embargo, es posible que enfrentemos algunos desafíos al usar este método y llegaremos a eso un poco más adelante en esta sesión.
Formulario y tabla de datos de demostración.
Necesitamos una tabla y un formulario. Ya tenemos una tabla adecuada con el nombre Sample creado en una sesión de tutorial anterior. Si ya ha descargado la base de datos de demostración, desde la segunda página de enlace proporcionada anteriormente, también puede usar esa base de datos para esta sesión. Usaremos los siguientes objetos de esa base de datos para nuestros experimentos de arrastrar y soltar:
- Tabla:Ejemplo
- Formulario:frmMuestra
La imagen de control de TreeView en frmSample con datos de demostración se proporciona a continuación como referencia:
Puede descargar la base de datos de demostración (ProjectMenu.zip ) de la página del segundo enlace anterior y extraiga el ProjectMenu.accdb base de datos.
Nuevo formulario para ejecuciones de prueba de arrastrar y soltar.
-
Abra la base de datos ProjectMenu.accdb.
-
Haz una copia de la tabla Ejemplo y asígnele el nombre Sample_bk, manténgalo seguro, necesitaremos sus datos originales sin cambios más adelante. Cuando experimentamos con el método de arrastrar y soltar, es necesario actualizar el valor del campo ParentId en la tabla de demostración de muestra. Pero necesitamos los datos originales más tarde, sin estos cambios.
-
Cree un nuevo formulario con el nombre frmDragDrop .
-
El diseño de formulario frmDragDrop se verá como la imagen que se muestra a continuación cuando termine con él.
-
Inserte el control TreeView de la lista de controles ActiveX y colóquelo en el formulario, dejando suficiente espacio sobre el control, para que podamos crear dos botones de comando y una etiqueta de encabezado sobre él. Arrastre el controlador de tamaño en la esquina inferior derecha para que sea lo suficientemente grande para mostrar todos los nodos, sin desplazarse.
-
Cambiar el Nombre Valor de propiedad de TreeView Control para TreeView0 .
-
Inserte un botón de comando arriba y en el borde izquierdo del control TreeView. Cambiar su Nombre Valor de propiedad para cmdExpand y Título valor para Expandir todo .
- Inserte un segundo botón de comando arriba y en el borde derecho del control TreeView. Cambiar su Nombre Valor de propiedad para cmdCollapse y el Título Valor de propiedad para Contraer todo.
-
Inserte un control de etiqueta encima de los botones de comando, lo suficientemente ancho para escribir el encabezado como se muestra arriba, y cambie su tamaño de fuente 14.
-
Ignore el control ImageList, por el momento, he comentado las líneas de código que modifican los números de índice de Node ImageList. Más adelante, puede importar el control ImageList con imágenes cargadas manualmente, desde nuestra base de datos de demostración de tutoriales anterior (de la cuarta página de enlace anterior) y usarlo para mostrar imágenes de nodos en nodos. Cuando se cambian las posiciones de los nodos durante las acciones de arrastrar y soltar, también debemos cambiar las imágenes de los nodos según la posición del nodo (nodo de nivel raíz o nodo secundario) en el control TreeView.
Código del módulo de formulario de arrastrar y soltar.
-
Muestre el módulo de código VBA del formulario frmDragDrop, copie y pegue el siguiente código VBA (esta es solo la primera mitad del código del módulo de formulario) en el módulo de clase del formulario frmDragDrop y guarde el formulario:
Option Compare Database Option Explicit Dim tv As MSComctlLib.TreeView Dim db As DAO.Database Dim rst As DAO.Recordset Dim imgListObj As MSComctlLib.ImageList Const KeyPrfx As String = "X" Private Sub Form_Open(Cancel As Integer) Set tv = Me.TreeView0.Object 'Set imgListObj = Me.ImageList1.Object 'tv.ImageList = imgListObj LoadTreeView End Sub Sub LoadTreeView() Dim strKey As String Dim strPKey As String Dim strText As String Dim strsQL As String strsQL = "SELECT * FROM Sample ORDER BY ID" Set db = CurrentDb Set rst = db.OpenRecordset(strsQL, dbOpenDynaset) tv.Nodes.Clear 'Add all Items are added as Root Nodes Do While Not rst.BOF And Not rst.EOF strKey = KeyPrfx & CStr(rst!ID) strText = rst!desc tv.Nodes.Add , , strKey, strText 'With tv.Nodes.Item(strKey) ' .Image = 1 ' .SelectedImage = 4 'End With rst.MoveNext Loop 'Prepare to update the Parent-Key of Nodes 'wherever applicable to move and position the Child Nodes strPKey = "" rst.MoveFirst Do While Not rst.EOF strPKey = Nz(rst!parentid, "") If Len(strPKey) > 0 Then strPKey = KeyPrfx & strPKey strKey = KeyPrfx & CStr(rst!ID) strText = rst!desc 'Move the Child Node under it's Parent-Node Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey) 'Update Image and SelectedImage Properties 'with ImageList Index numbers 'With tv.Nodes.Item(strKey) ' .Image = 2 ' .SelectedImage = 3 'End With End If rst.MoveNext Loop rst.Close Set rst = Nothing Set db = Nothing End Sub Private Sub TreeView0_NodeClick(ByVal Node As Object) Dim SelectionNode As MSComctlLib.Node 'Ensure that the clicked node equals the selected node in the tree If Not Node Is Nothing Then Set SelectionNode = Node If SelectionNode.Expanded = True Then SelectionNode.Expanded = False Else SelectionNode.Expanded = True End If End If End Sub Private Sub cmdCollapse_Click() Dim tmpnod As MSComctlLib.Node For Each tmpnod In tv.Nodes If tmpnod.Expanded = True Then tmpnod.Expanded = False End If Next End Sub Private Sub cmdExpand_Click() Dim tmpnod As MSComctlLib.Node For Each tmpnod In tv.Nodes If tmpnod.Expanded = False Then tmpnod.Expanded = True End If Next End Sub
Sé que está familiarizado con el Código anterior, si ya ha pasado por los Episodios anteriores, excepto el LoadTreeView() subrutina con algunos cambios. Aquí, llenar los nodos TreeView se ha dividido en un proceso de dos pasos.
Brevemente, esto es lo que sucede en esta Subrutina.
Todos los registros en Muestra La tabla se cargó como nodos de nivel raíz de TreeView Control, con un valor de campo de ID como clave, en el primer paso.
Nuevamente, estos registros se leyeron por segunda vez y se buscó un valor en el Id de padre campo, si está vacío, el nodo se mantendrá como nodo de nivel raíz.
Si el campo ParentID tiene un valor, identifique el nodo con el valor de ParentID como Node-Key y mover el nodo actual como su nodo secundario, o su [Relativo] Parámetro (de Agregar () Método) el valor se actualiza.
-
Aunque parece que el procedimiento de relleno de nodos de dos pasos es un ejercicio innecesario, hay una buena razón por la que tenemos que seguir este método. Volveremos sobre esto un poco más adelante y lo sabrás sin muchas explicaciones.
-
Sobre el Diseño del Formulario, le he dado un Control ImageList. Puede insertar el ImageList ActiveX Control y cargue algunas imágenes manualmente desde el disco, o copie y pegue este control con imágenes de descargas de bases de datos de demostración anteriores. En cualquier caso, asegúrese de que el nombre del control ImageList sea ImageList1 . De lo contrario, debe cambiar el nombre en el Código.
-
Después de eso, habilite las líneas comentadas en el procedimiento de evento Form_Open(). Habilite las siguientes líneas eliminando el símbolo de comentario del principio de la línea:
'Set imgListObj = Me.ImageList1.Object 'tv.ImageList = imgListObj
-
En el TreeView0_ OLEDragDrop() La subrutina (en la segunda parte del código VBA) habilita los parámetros de índice de imagen de los nodos, al eliminar también los símbolos de comentario de esas líneas. Con estos cambios, las imágenes de nodo aparecerán en el control TreeView. Si tiene un control ImageList propio con imágenes cargadas, cambie los números de índice en función de la imagen que le gustaría insertar en los nodos.
El TreeView0_NodeClick() Procedimiento de evento Expande el nodo actual, si los nodos secundarios están colapsados; de lo contrario, los nodos secundarios se colapsarán. Normalmente esta acción se controla (sin código) haciendo clic en +/- Símbolo en la línea de árbol del nodo con nodos secundarios.
Las Subrutinas cmdExpand_Click() y cmdCollapse_Click() Eventos Expande todos los nodos y contrae todos los nodos respectivamente.
Cuando se ejecuta el código anterior, la pantalla se parece a la imagen de vista de formulario que se muestra a continuación:
-
Puede guardar el frmDragDrop Formulario y ábralo en Vista normal. Si todo salió bien, verá la pantalla anterior. Pruebe Expandir todo y Ocultar todo Botones de comando y verifique si también funcionan. De lo contrario, vuelva a verificar que las siguientes configuraciones sean correctas o no:
-
i) El nombre del control TreeView es:TreeView0
-
ii) Mostrar la hoja de propiedades de Expandir todo Botón de comando y seleccione [Procedimiento de evento] en Al hacer clic Propiedad del evento.
-
iii) Asegúrese de que la misma configuración esté intacta para Contraer todo Botón de comando también.
-
iv) Haga clic en un nodo que tenga nodos secundarios para ver si colapsan o se expanden con clics repetidos.
-
v) Si se coloca ImageList Control en el formulario, su nombre debe ser ImageList1 .
Procedamos con la segunda parte del código VBA que implementa los eventos de arrastrar y soltar.
Segunda mitad del código VBA.
-
Copie la siguiente segunda parte del código VBA, en el módulo de formulario frmDragDrop, que implementa la acción de arrastrar y soltar, y péguelo debajo del código existente:
Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long) Set Me.TreeView0.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) Dim SelectedNode As MSComctlLib.Node Dim nodOver As MSComctlLib.Node If tv.SelectedItem Is Nothing Then 'Select a node if one is not selected Set SelectedNode = tv.HitTest(x, y) If Not SelectedNode Is Nothing Then SelectedNode.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 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 sourceNode As MSComctlLib.Node Dim SourceParentNode As MSComctlLib.Node Dim targetNode As MSComctlLib.Node Dim tmpRootNode As MSComctlLib.Node Dim strtmpNodKey As String Dim ChildNode As MSComctlLib.Node Dim strSPKey As String Dim strTargetKey As String Dim strsQL As String Dim intKey As Integer Dim intPKey As Integer On Error Resume Next Select Case Screen.ActiveControl.Name Case TreeView0.Name Set sourceNode = tv.SelectedItem End Select 'Get Source Parent Node & Target Node Reference Set SourceParentNode = sourceNode.Parent Set targetNode = tv.HitTest(x, y) 'If any errors then exit If Err <> 0 Then MsgBox Err & " : " & Err.Description, vbInformation + vbCritical, "OLEDragDrop()" Err.Clear Exit Sub Else On Error GoTo 0 End If 'Get/define Source parent Node Key to compare it with Target Node Key If SourceParentNode Is Nothing Then strSPKey = "Empty" Else strSPKey = SourceParentNode.Key End If 'Check the Target Node/Location and define the Key Select Case True Case targetNode Is Nothing strTargetKey = "Empty" Case targetNode.Key = "" strTargetKey = "Empty" Set targetNode = Nothing Case Else strTargetKey = targetNode.Key End Select 'Make sure the Target Node is not the source Node's own parent If strTargetKey = strSPKey Then Exit Sub 'Track User's Node move action, check for error. On Error Resume Next If targetNode Is Nothing Then 'If target Node is Nothing (the Node dropped in the empty area), 'then the Node must be moved to the Root-level 'save the original sourceNode.Key strtmpNodKey = sourceNode.Key 'Modify the source Node Key, with addition of some text, say 'Empty', like 'X5Empty' 'So that a temporary Node can be created with the original source Node key. 'Note: Two Nodes with the same Key cannot remain in memory at the same time. 'The Source Node with key 'X5Empty' deleted later, 'temporary Node takes it's droped location. sourceNode.Key = sourceNode.Key & strTargetKey 'Create the temporary Root Node, with original sourceNode Key Set tmpRootNode = tv.Nodes.Add(, , strtmpNodKey, sourceNode.Text) 'define the Root Node image indexes 'With tmpRootNode ' .Image = 1 ' .SelectedImage = 4 'End With 'Move all child Nodes from SourceNode,if any, 'as tmpRootNode's Children Do Until sourceNode.Children = 0 Set sourceNode.Child.Parent = tmpRootNode 'modify Node image indexes 'With sourceNode ' .Image = 2 ' .SelectedImage = 3 'End With Loop 'Delete the Source Node with modified Key from TreeView tv.Nodes.Remove sourceNode.Index 'Move the tmpRootNode with original Key 'to the dropped location on TreeView Set sourceNode = tmpRootNode Else 'Move the sourceNode under targetNode as child Set sourceNode.Parent = targetNode 'modify Node image indexes 'With sourceNode ' .Image = 2 ' .SelectedImage = 3 'End With End If 'Notify, if there was an Error then Exit, else Update PrentID of related Record. If Err <> 0 Then MsgBox Err & " : " & "Unable to move:" & vbCrLf & Err.Description, vbInformation + vbCritical, "DragDrop2()" Exit Sub Else 'Build and execute the SQL statement to update the record If targetNode Is Nothing Then intKey = Val(Mid(sourceNode.Key, 2)) strsQL = "UPDATE Sample SET ParentID = Null" & _ " WHERE ID = " & intKey Else intKey = Val(Mid(sourceNode.Key, 2)) intPKey = Val(Mid(targetNode.Key, 2)) strsQL = "UPDATE sample SET ParentID = " & intPKey & _ " WHERE ID = " & intKey End If 'Modify the table records CurrentDb.Execute strsQL, dbFailOnError 'If an error raised then refresh TreeView and exit If Err <> 0 Then MsgBox Err & " : " & Err.Description LoadTreeView 'Refresh/display TreeView without changes Else 'Sort Nodes If sourceNode.Parent Is Nothing Then sourceNode.Root.Sorted = True Else sourceNode.Parent.Sorted = True End If tv.Nodes(sourceNode.Key).Selected = True End If End If On Error GoTo 0 End Sub Private Sub TreeView0_OLECompleteDrag(Effect As Long) 'Turn off the drophighlight Set tv.DropHighlight = Nothing End Sub Private Sub Form_Close() Set tv = Nothing End Sub
Para la acción de arrastrar y soltar, hay cuatro subrutinas, se ejecutaron automáticamente cuando arrastra los nodos, resalta el nodo cuando se mueve sobre otros nodos y finalmente lo suelta en un nodo diferente o en el área vacía del nivel raíz. .
Las Principales Subrutinas del Código.
- TreeView0_OLEStartDrag() - Inicializa el elemento seleccionado y establece el Nodo en Nada
- TreeView0_OLEDragOver() - Funciona como el evento de movimiento del mouse, resalta el nodo, cuando arrastra un nodo sobre él, en el camino hacia el nodo de destino.
- TreeView0_OLEDragDrop() – Realiza comprobaciones y controles, coloca los nodos en la ubicación soltada y actualiza el registro en la tabla base.
- TreeView0_OLECompleteDrag() - La propiedad DropHighlight se establece en Nada.
Podemos hacer los trabajos de arrastrar y soltar con TreeView0_OLEDragDrop() Subrutina sola. En ese caso, no habrá ningún nodo resaltado, cuando el nodo de origen se mueva sobre otros nodos, de una ubicación a otra, excepto que el puntero del mouse cambia para arrastrar una segunda flecha detrás de él, como en la imagen de muestra que se muestra a continuación. :
Por lo tanto, prestaremos atención a esta subrutina y revisaremos el Código en detalle desde el principio. Al principio de la subrutina, hemos declarado los Nodos y Variables de Cadena necesarios, y otros.
En lugar de repetir análisis línea por línea aquí, he comentado cada línea/sección de códigos adecuadamente para que comprenda lo que hace cuando revisa el Código. Puede revisarlos.
La secuencia de eventos Drap Drop
Entendamos la secuencia de Eventos, el Usuario Selecciona un nodo, arrastra sobre otros nodos en el camino hacia su destino final y solta en el nodo de destino. O colóquelo en el área vacía del control TreeView para convertirlo en un nodo de nivel raíz.
Cuando arrastra un Nodo sobre otro Nodo-Texto, el Nodo-Texto se resalta, diciendo que su posición actual está en este Nodo en el camino, dondequiera que vaya desde aquí. Cuando se mueve fuera del texto del nodo, el resaltado desaparece. Esto sucede hasta el nodo de destino. El TreeView0_OLEDragOver() La subrutina se encarga de esta acción de resaltado.
Cuando suelta un nodo en algún lugar, el TreeView0_OLEDragDrop() La subrutina se sobrecarga. Aquí, tenemos que analizar las intenciones del Usuario y tomar las medidas apropiadas. La siguiente información debe guardarse y analizarse para mover el Nodo a la ubicación correcta.
Información importante a tener en cuenta.
-
La referencia de nodo de origen, la clave de nodo y los valores de ID de padre, hijos de nodo, si los hay.
-
El nodo de destino o referencia de ubicación, clave de nodo.
-
Si el objetivo no es un nodo sino el área vacía del control TreeView, entonces el nodo de origen se moverá a la posición de nivel raíz.
-
El nodo de origen cuando se coloca en otro nodo, el nodo de destino se convierte en el nuevo padre del nodo de origen.
-
Si el nodo de origen tiene sus propios elementos secundarios, también se deben mover con su elemento principal.
-
** Cuando el nodo se arrastre y suelte en su propio nodo principal, ignore esta acción.** Por ejemplo, compruebe la imagen de arriba. Si arrastramos el TextBox Nodo y suéltelo en su nodo principal Controles, o arrastra los Controles Nodo y suéltelo en su formulario de nodo principal entonces esos movimientos serán ignorados. -
** Si nivel raíz El nodo se arrastra y suelta en el área vacía, luego no se realizará ninguna acción porque ya es un nodo de nivel raíz.
Para todos los movimientos válidos de Node, necesitamos actualizar el ParentID valor de campo del registro relacionado en la muestra Mesa.
Caída de nodo en el área vacía del nivel raíz.
En el caso del artículo número 3 arriba, tenemos que crear un Nodo de nivel Raíz, con el mismo Número de ID del Nodo Fuente, lo cual no está permitido. El valor de clave duplicado no está permitido en la jerarquía de TreeView. Esta es la única área del Código, donde encontrará un poco confuso el procedimiento seguido allí.
El procedimiento es el siguiente:
-
Modifique la clave de nodo TreeView existente con la adición de texto adicional (diga Clave X5 cambiar a X5Vacío ), para evitar conflictos de clave, mientras se crea un nodo temporal con la clave original.
-
Crear un temporal Nodo con la clave original:X5.
-
Mueva todos los nodos secundarios del nodo de origen, si los hay, como nodos secundarios al nodo temporal.
-
Elimine el nodo de origen TreeView con la clave modificada:X5Empty desde el control TreeView, pero el registro relacionado en la tabla de muestras no se toca.
-
Mover el temporal Nodo con la clave original X5 con sus hijos a la posición de nivel raíz del control TreeView.
-
Actualice el campo ParentID del registro relacionado con una cadena de longitud cero ("") para marcarlo como un nodo de nivel raíz.
Experimentos propios de arrastrar y soltar.
Puede probar algunos experimentos de arrastrar y soltar y ver cómo funciona. Seleccione un nodo, haga clic y mantenga presionado el botón izquierdo del mouse, arrastre el nodo y suéltelo en otro nodo, o suéltelo en un área vacía del control TreeView. Cuando arrastra el nodo sobre otro texto de nodo, se resalta y cuando está fuera del nodo, el resaltado desaparece. El nodo arrastrado aparecerá en la nueva ubicación donde lo soltó. Puede repetir este experimento de arrastrar y soltar seleccionando un solo nodo o nodo con hijos.
Basado en este movimiento de Nodos, el ParentID del registro relacionado el valor del campo se actualizará con la Clave valor (ID) del registro relacionado con el nodo de destino.
¿Por qué un procedimiento de llenado de nodos en dos pasos?
Ahora, volveremos a LoadTreeView() Subrutina, para echar un segundo vistazo al proceso de dos pasos que hemos adoptado para llenar todos los nodos del control TreeView.
-
Todos los registros de la muestra La tabla se agrega inicialmente como nodos de nivel raíz, utilizando el valor del campo de ID como clave de nodo.
-
En la segunda pasada de los registros, si el valor del campo ParentID está vacío, ese nodo permanecerá como nodo de nivel raíz, sin cambios.
-
Todos los demás registros relacionados con nodos con ParentID Value se mueven correctamente bajo su nodo principal.
Naturalmente, surge la pregunta, ¿por qué tenemos que hacerlo de esta manera?
Haremos un experimento simple para aclarar la respuesta sin explicarla con demasiadas palabras. Es posible que ya haya realizado algunas ejecuciones de prueba de arrastrar y soltar y haya reorganizado los nodos, en el proceso actualizó los valores de ParentID de esos registros con el cambio. Por lo tanto, debemos restablecer los valores de registro a su estado original en la muestra Table, antes de comenzar una nueva demostración.
Ya hemos creado una copia de nuestra Tabla Muestra anteriormente, con el nombre Sample_bk como copia de seguridad. Eliminar la muestra Tabla y hacer una copia de Sample_bk con el nombre original:Muestra .
Abra la tabla y vea los registros y sus valores de campo ParentID. La imagen de muestra de la tabla se muestra a continuación:
Los valores de campo de ID son autonuméricos y están todos en orden secuencial y todos los valores de ID son únicos. La siguiente regla simple rige la adición de un nodo secundario al control TreeView.
La regla del nodo secundario simple: El ID de padre Valor del campo (Clave principal ) en un registro espera que ya exista un nodo principal en el control TreeView, con el mismo valor que Node-Key (la identificación).
Verifique el tercer registro desde arriba, en la imagen de la tabla anterior. El valor del campo ParentID es 2 y el ID del registro actual es 3. En este caso, el registro con ID 2 se agregará al Control TreeView antes de que intentemos agregar el tercer registro al Nodo. Ambos registros no están necesariamente uno al lado del otro. Verifique el registro con el número de ID 21, su valor de campo ParentID es 12, menos que el valor de ID de registros actual 21.
En cualquier caso, cuando el programa encuentra el valor ParentID en un registro, asume que el registro con el valor de ID igual al ParentID ya se agregó como un nodo en el control TreeView en el ciclo anterior de llenado de los nodos.
Justificación del procedimiento de dos pasos.
Probemos algunas ejecuciones de prueba de arrastrar y soltar. Pero, antes de eso, tenemos un Formulario con el nombre frmSample, que que hemos usado en la primera sesión del tutorial, y en la que hemos cargado todos los nodos TreeView de una sola vez. Sí, hemos seguido el mismo método hasta ahora y necesitamos algún cambio a partir de ahora. Pero, antes de eso, abramos el formulario anterior y veamos cómo aparecen los Nodos en el Formulario.
-
Abra el formulario frmSample para ver cómo se ve la visualización de TreeView, con los registros de la tabla de muestra, cargados con la regla anterior.
-
Si ha terminado de ver los nodos TreeView, cierre el formulario.
-
Ahora, abra el frmDragDrop Forma. Nos estamos preparando para arrastrar y soltar un nodo.
-
Seleccione el nodo con la tabla de texto de nodo, Haga clic y mantenga presionado el botón izquierdo del mouse, arrástrelo y suéltelo en el Nodo, con el Formulario de Nodo-Texto.
-
La Mesa Nodo con sus campos de nodo secundario inmediatos y sus nodos secundarios se mueven como nodos secundarios bajo el formulario Nodo.
-
Cierra el formulario frmDragDrop y ábrelo de nuevo. Los nodos aparecerán correctamente, donde los haya soltado, como la imagen que se muestra a continuación.
-
Ahora, cierre el Formulario frmDragDrop.
-
Abra el formulario frmSample para ver cómo aparece este cambio en este Formulario. Recibirá un mensaje de error, Elemento no encontrado con Número de error:35601.
-
Seleccione el botón de comando de depuración para ir a la línea de código resaltada, donde ocurrió el error.
-
Apunte el mouse sobre la nodKey Param del método Add(), muestra X3, punto el ratón sobre la ParentKey parámetro y muestra X7.
Mirando estos dos valores de parámetros, podemos suponer que estamos en el registro con el valor de ID 3 y tratando de designar este nodo como un nodo secundario, a otro nodo que aún no se ha rellenado en el Control TreeView, con valor de ID 7.
-
Presiona F5 Presione la tecla para abrir el mismo cuadro de diálogo nuevamente y haga clic en Terminar Botón de comando para detener el programa y mostrar el formulario en la ventana de la base de datos. Cierre el formulario frmSample.
-
Abra la muestra Tabla para ver la disposición de los números ParentID, después de nuestra acción de arrastrar y soltar. Los registros se verán como la imagen que se muestra a continuación y he resaltado el registro que provocó el error con el valor de ParentID 7 y mostrando su posición de registro principal.
Siguiendo el procedimiento normal de llenado de nodos anterior, estamos en la tercera posición de registro. Dado que los registros ParentID valor 7, el Nod con ID valor 7 debe estar presente en el control TreeView. El nodo con valor de ID 7 aún no está poblado en el control TreeView, pero estamos tratando de hacer referencia al nodo inexistente y esto desencadena un error.
Incluso si ordena los registros en el orden del campo ParentID, la nueva disposición de los registros se verá como la imagen que se muestra a continuación:
Ahora, el nodo principal de otro registro no está en la posición esperada.
Por lo tanto, en estas circunstancias, nuestro enfoque de carga de TreeView Nodes de dos pasos funciona tanto para las acciones normales como para después de arrastrar y soltar.
En el primer paso, rellene todos los registros como nodos de nivel raíz en el control TreeView utilizando el valor del campo ID como clave de nodo.
Ahora, todos los Nodos de todos los registros están disponibles en el Control TreeView. Será fácil moverlos por donde queramos. No dice que ninguno de los nodos requeridos existe en TreeView.
En la segunda pasada en el mismo conjunto de registros, los registros con valores de campo ParentID vacíos no se tocan y se les permite permanecer como nodos de nivel raíz. En otros casos, mueve el nodo como nodo secundario debajo de su nodo principal, actualizando el [Relativo] Parámetro del Nodo con la siguiente Declaración:
Set tv.Nodes.Item(strKey).Parent = tv.Nodes.Item(strPKey)
This is what we do through the second pass on the same set of records. You may do it by resetting the Record Pointer to the first record, by executing rst.MoveFirst before the Do . . . Loop, EOF conditions and rst.MoveNext to access each record as we normally do.
Second Step in Reverse Order.
Or you may do it in reverse order. After populating all records as Root-level Nodes the Record Pointer will be beyond the last record and on the EOF posición. You may reset the record pointer to the last record, by executing rst.MoveLast before the Do . . . Loop BOF check, and execute rst.MovePrevious to access each record and move the Nodes correctly under its p arent Node. But, the Nodes may load slightly differently in the placement order of Nodes.
You may try this out yourself with the above-suggested change of Code and see the result.
Download Demo Database
- Módulo de clase MS-Access y VBA
- Matrices de objetos de clase VBA de MS-Access
- Clase base de MS-Access y objetos derivados
- VBA Base Class and Derived Object-2
- Variantes de clase base y objeto derivado
- Módulo de clase y conjunto de registros de MS-Access
- Módulo de clase de acceso y clases contenedoras
- Transformación de la funcionalidad de la clase contenedora