Execute a trapping operation
After defining TreeView, now you should prepare how to move your elements around, most developers are very similar to general concepts when handling drag and drop operations, whether using Visual C Visual Basic or any one. NET language, so I have been using the following four methods:
MouseDown ----- User Choose content
Dragenter --- User started dragging the selected item
Dragover --- User Drag Selecting Project After another project
Dragdrop --- User puts down the selected item in some place
Executing these methods is appropriate to give the user to give visual feedback respectively, and tell the user how they are executed, and do not use the details of the given context, so there are three direct problems. be considered:
1. How do you match a node in the TreeView control and nodes in the underlying XML document
2. For physical nodes, how can users perform XML documents with graphics
3. How do you effectively perform large XML documents. If such a change must be strengthened, you don't want to bind no necessary things to the user interface.
Listing 1
A TreeNode's position maps to an XML node using an XPath query. Private Sub XmlTreeView_MouseDown (ByVal sender As Object, ByVal e As _ System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown 'First check whether we've clicked on a node in the tree view; if not, 'just return Dim pt As New Point (eX, eY) drag_node = Me.GetNodeAt (pt) If drag_node Is Nothing Then return' Highlight the node and build an xpath query so that we can remove it later xpath_remove_query = buildXPathQuery (drag_node) Me.SelectedNode = drag_node 'Decide whether we're going to perform an intra-folder rearrangement (right' mouse button) or a genuine drag-and-drop (left mouse button); 'we do this in the MouseDown rather than DragEnter method, since by the time 'DragEnter fires, the mouse may well have been dragged to a different node If e.Button = System.Windows.Forms.MouseButtons.Right Then right_mouse_drag = True Else right_mouse_drag = False End IfEnd SUB P Rivate function buildxpathQuery (byval node as system.windows.forms.treenode) AS STRING DIM Query As String = "" Do Query = "* [" & XPath_filter & "] [" & (Node.Index 1) & "] / "& query node = node.parent loop while not (node is nothing) Return query.substring (0, query.length - 1) End function shows the mousedown handle and the help method it calls BuildXPathQuery, first code check one selected Node, then store TREENODE (Drag_Node) and the XPath_Remove_query of the XML document root node by using pre-defined filters and to associate it to the XML document root node. For example, the following query determines the second child of the root node of the tree has five children folders, one folder can be used with query "attribute :: id." Uniquely determined
* [attribute :: id] [2] / * [attribute :: id] [5] When the user drags a node to another location, the code list 1 provides sufficient information about the XMLNode associated with Treenode and Treenode. You may think that you can get the same effect, but there is no need to refer to screening, and simply specify the "second child of the" The second child of the root node to the first child's node "such thing, but here is not what you think Then, it should be that the filter forces TreeView's node hierarchical hierarchical level and the XML document corresponds to one by one. There is no, such direct use may be unwise, for example, assume that the filter matches the following structure:
[0] Contacts> [0]
[0] Contacts> [0]
Thus drag_drop_active variable properties as disclosed directly DragDropActive [C #] private void XmlTreeView_DragEnter (object sender, System.Windows.Forms.DragEventArgs e) {// Allow the user to drag tree nodes within a // tree if (e.Data.GetDataPresent ("System.Windows.Forms.treenode", true) {E.Effect = DragDropeffects.move; Drag_Drop_Active = true;} else e.effect = DragDropeffects.none;}
[VB] Private Sub XmlTreeView_DragEnter (_ ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles MyBase.DragEnter 'Allow the user to drag tree nodes within a tree If e.Data.GetDataPresent (_ " System.Windows.Forms.TreeNode ", True) Then e.Effect = DragDropEffects.Move drag_drop_active = True Else e.Effect = DragDropEffects.None End if End Sub when you drag a folder DragOver is constantly invoked Private Sub XmlTreeView_DragOver ( ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles MyBase.DragOver 'Fired continuously while a tree node is dragged. We need to override this to' provide appropriate feedback If e.Data.GetDataPresent ( "System. Windows.Forms.TreeNode ", True) Then 'Determine which node we are dragging over Dim pt As Point = Me.PointToClient (New Point (eX, eY)) Dim drop_node As TreeNode = Me.GetNodeAt (pt)' If it's the Same as the one we last ragged over, take no further action If drop_node Is last_drop_node Then Return End If 'Otherwise highlight the node as a potential drop target Me.SelectedNode = drop_node last_drop_node = drop_node' If the drop node and drag node are the same, indicate that the drag is 'disallowed and take no further action (as per Explorer) If drag_node Is drop_node Then e.Effect = DragDropEffects.None Return End If If right_mouse_drag Then' Right mouse drag-and-drop operations constitute intra-folder '
rearrangements which provide continuous graphical feedback 'We need to cache the drop node's parent, since it will' be inaccessible if we remove it from the tree Dim drop_parent As TreeNode = drop_node.Parent 'Check if it's at the same level as the node being dragged If drag_node.Parent Is drop_parent Then 'Temporarily remove the drop node's siblings from the tree; then add' them back in a different order Dim siblings (drop_parent.Nodes.Count) As System.Windows.Forms.TreeNode Dim count As Integer = siblings .Length - 1 dim item as integer for item = 0 to count - 1 siblings (item) = Drop_parent.nodes (0) Drop_parent.nodes (0) .remove () Next for item = 0 to count - 1 if Siblings (item Is Drop_Node Then Drop_Parent.nodes.Add (Drag_Node) Else If siblings (item) Is drag_node Then drop_parent.Nodes.Add (drop_node) Else drop_parent.Nodes.Add (siblings (item)) End If End If Next 'Highlight the new node last_drop_node = drag_node e.Effect = DragDropEffects.Move Me .SelectedNode = DRAG_NODE ELSE E.Effect = DragDropeffects.none End IF Else '
If the user is left-button dragging, disallow (pointless) attempts' to drag a node into its parent's folder (as per Explorer) If drag_node.Parent Is drop_node Then e.Effect = DragDropEffects.None Else e.Effect = DragDropEffects.Move End if end if end ifnd Sub For execution efficiency, the code first checks whether the file that is dragged since the last call Dragover has changed, and if it changes, the code is then determined in the drag type in the process. I used to allow the user to finally reorder and set the hierarchy, I choose a behavior similar to Windows (as long as it is defined), use my solution in other places. So let the user use the left button to copy or move the folder very unnatural, we should let the user use the right click to process the folder. However, this will create a small problem because the two drag will process different methods: the left button is dragged until the end of the drag, and the right-click drag will continue feedback, even constantly dragging Until the user released the mouse button, the document does not have a physical location. In this way, the code check is the dragged node is a node's brothers node. If so, all child nodes of the parent node are separated from the tree. Out, then drag and drop the switching node location, then add these child nodes to go back. The result is: When the release operation is completed, the underlying data source is updated according to the current visual expression, and the hidden underlying data and the data visual expression can be kept synchronized. A better handling method is: Constant display update operations, so users can immediately get feedback on drag, and XML documents only need to be updated once when dragging is completed.
The drag and drop operation of the left button does not require a special code, the DRAG / DROP API can process feedback. The user completes the drag and drop operation by loosening the mouse button, refer to the following code list 3Listing 3. XmltreeView_dragdrop and helper methods: the xmltreeView_dragdrop and its helper swapXmlDocumentNodes methods provide logic to decide where a node belongs among its siblings Private Sub XmlTreeView_DragDrop (ByVal sender As Object, ByVal e As _ System.Windows.Forms.DragEventArgs) Handles MyBase.DragDrop 'Cancel drag / drop drag_drop_active = False' Check that we are dropping nodes within the same tree view If e.Data.GetDataPresent ( "System.Windows.Forms.TreeNode", True) = False Then Return End If 'If it's a right-mouse drag-and-drop operation, the tree view will already 'show the updated hierarchy; so it's just a matter of updating the xml' document to match the tree view If right_mouse_drag Then swapXmlDocumentNodes () drag_node = Nothing last_drop_node = drag_node xpath_remove_query = "" Else 'Determine which node we are DR opping onto Dim pt As Point = Me.PointToClient (New Point (eX, eY)) Dim drop_node As TreeNode = Me.GetNodeAt (pt) 'Do nothing if the drag and drop target are the same node If drag_node Is drop_node Then Return End If If drop_node Is Nothing Then 'Do not allow the user to drag nodes off the tree. Though the tree view' would not complain, any attempt to create an xml document with 2 roots 'would cause problems Return End If'
Add the new node where it was dropped drag_node.Remove () drop_node.Nodes.Add (drag_node) 'And update the xml document to match the new tree view hierarchy swapXmlDocumentNodes () drag_node = Nothing last_drop_node = drag_node xpath_remove_query = "" End IfEnd Sub Private Sub swapXmlDocumentNodes () 'This method updates the xml document bound to the tree view so that the two node' hierarchies are the same; it determines appropriate xpath queries to remove and 'reinsert the node in question by comparing the tree view's structure before and 'after the drag / drop operation took place Dim node As System.Xml.XmlNode node = xml_document.DocumentElement.SelectSingleNode (xpath_remove_query) node.ParentNode.RemoveChild (node)' Create a query to determine where the node should be reinserted Dim xpath_insert_query As String = buildxpathQuery (DRAG_NODE) 'WE Are ONLY INTERESTED IN THE PARENT Portion of the Inser t query xpath_insert_query = xpath_insert_query.Substring (0, xpath_insert_query.LastIndexOf ( "/")) Dim insert_parent As System.Xml.XmlNode = xml_document.DocumentElement.SelectSingleNode (xpath_insert_query) If drag_node.Parent.Nodes.Count = 1 Then 'Special case : if as a result of the drag / drop operation some parent without '. previous children gained a child, just add the child to the parent insert_parent.AppendChild (node) Else' Otherwise we need to insert the child at its appropriate position; XmlNode '