Index: Core/Common/src/Core.Common.Controls.TreeView/DragDropHandler.cs =================================================================== diff -u -rdb46e1af6dc390f8e9a9bea0ba1a3529559d8f3b -r514d2e7d8903b5846e71ce5e066f574f89f1bb2b --- Core/Common/src/Core.Common.Controls.TreeView/DragDropHandler.cs (.../DragDropHandler.cs) (revision db46e1af6dc390f8e9a9bea0ba1a3529559d8f3b) +++ Core/Common/src/Core.Common.Controls.TreeView/DragDropHandler.cs (.../DragDropHandler.cs) (revision 514d2e7d8903b5846e71ce5e066f574f89f1bb2b) @@ -61,29 +61,19 @@ RemovePlaceHolder(treeView); var point = treeView.PointToClient(new Point(e.X, e.Y)); - var nodeOver = treeView.GetNodeAt(point); + TreeNode nodeOver = treeView.GetNodeAt(point); var draggedNode = (TreeNode) e.Data.GetData(typeof(TreeNode)); if (nodeOver == null) { return; } - // Handle dragged items which were originally higher up in the tree under the same parent (all indices shift by one) - if (e.Effect.Equals(DragDropEffects.Move) && draggedNode.Parent == nodeDropTarget && nodeOver.Index > draggedNode.Index && dropAtLocation > 0) - { - dropAtLocation--; - } + SetDropAtLocation(e, draggedNode, nodeOver); - // Ensure the drop location is never < 0 - if (dropAtLocation < 0) - { - dropAtLocation = 0; - } + TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(nodeDropTarget.Tag); + TreeNode formerParentNode = draggedNode.Parent; - var treeNodeInfo = getTreeNodeInfoForData(nodeDropTarget.Tag); - var formerParentNode = draggedNode.Parent; - // Move the tree node formerParentNode.Nodes.Remove(draggedNode); nodeDropTarget.Nodes.Insert(dropAtLocation, draggedNode); @@ -116,10 +106,10 @@ lastDragOverPoint = new Point(e.X, e.Y); var point = treeView.PointToClient(lastDragOverPoint); - var nodeOver = treeView.GetNodeAt(point); + TreeNode nodeOver = treeView.GetNodeAt(point); var draggedNode = (TreeNode) e.Data.GetData(typeof(TreeNode)); - if (nodeOver == null || nodeOver == draggedNode || IsChildOf(nodeOver, draggedNode)) + if (nodeOver == null || nodeOver == draggedNode || IsDropTargetChildOfDraggedNode(nodeOver, draggedNode)) { RemovePlaceHolder(treeView); @@ -128,14 +118,14 @@ ScrollIntoView(point, nodeOver, treeView); - var placeholderLocation = GetPlaceHoldersLocation(treeView, draggedNode, nodeOver, e, getTreeNodeInfoForData); + PlaceholderLocation placeholderLocation = GetPlaceHoldersLocation(treeView, draggedNode, nodeOver, e, getTreeNodeInfoForData); if (nodeDropTarget == null) { return; } - var treeNodeInfo = getTreeNodeInfoForData(nodeDropTarget.Tag); + TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(nodeDropTarget.Tag); var canDrop = treeNodeInfo.CanDrop != null && treeNodeInfo.CanDrop(draggedNode.Tag, nodeDropTarget.Tag); e.Effect = canDrop ? DragDropEffects.Move : DragDropEffects.None; @@ -166,11 +156,10 @@ public void HandleItemDrag(FormsTreeView treeView, ItemDragEventArgs e, Func getTreeNodeInfoForData) { var draggedNode = (TreeNode) e.Item; - var treeNodeInfo = getTreeNodeInfoForData(draggedNode.Tag); + TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(draggedNode.Tag); var parentTag = draggedNode.Parent != null ? draggedNode.Parent.Tag : null; - var canDrag = treeNodeInfo.CanDrag != null && treeNodeInfo.CanDrag(draggedNode.Tag, parentTag); - if (!canDrag) + if (treeNodeInfo.CanDrag == null || !treeNodeInfo.CanDrag(draggedNode.Tag, parentTag)) { return; } @@ -192,6 +181,21 @@ RemovePlaceHolder(treeView); } + private void SetDropAtLocation(DragEventArgs e, TreeNode draggedNode, TreeNode nodeOver) + { + // Handle dragged items which were originally higher up in the tree under the same parent (all indices shift by one) + if (e.Effect.Equals(DragDropEffects.Move) && draggedNode.Parent == nodeDropTarget && nodeOver.Index > draggedNode.Index && dropAtLocation > 0) + { + dropAtLocation--; + } + + // Ensure the drop location is never < 0 + if (dropAtLocation < 0) + { + dropAtLocation = 0; + } + } + private void CreatePlaceholder(FormsTreeView treeView, TreeNode node, PlaceholderLocation placeHolderLocation) { if (lastPlaceholderNode == node && lastPlaceholderLocation == placeHolderLocation) @@ -221,16 +225,16 @@ } } - private static bool IsChildOf(TreeNode childNode, TreeNode node) + private static bool IsDropTargetChildOfDraggedNode(TreeNode dropTarget, TreeNode draggedNode) { - while (childNode != null && childNode.Parent != null) + while (dropTarget != null && dropTarget.Parent != null) { - if (childNode.Parent.Equals(node)) + if (dropTarget.Parent.Equals(draggedNode)) { return true; } - childNode = childNode.Parent; // Walk up the tree + dropTarget = dropTarget.Parent; // Walk up the tree } return false; @@ -239,19 +243,20 @@ private static void ScrollIntoView(Point point, TreeNode nodeOver, FormsTreeView treeView) { int delta = treeView.Height - point.Y; + double halfTreeViewHeight = treeView.Height/2.0; - if (delta < treeView.Height/2 && delta > 0) + if (delta < halfTreeViewHeight && delta > 0) { - var nextVisibleNode = nodeOver.NextVisibleNode; + TreeNode nextVisibleNode = nodeOver.NextVisibleNode; if (nextVisibleNode != null) { nextVisibleNode.EnsureVisible(); } } - if (delta > treeView.Height/2 && delta < treeView.Height) + if (delta > halfTreeViewHeight && delta < treeView.Height) { - var previousVisibleNode = nodeOver.PrevVisibleNode; + TreeNode previousVisibleNode = nodeOver.PrevVisibleNode; if (previousVisibleNode != null) { previousVisibleNode.EnsureVisible(); @@ -268,7 +273,7 @@ { if (nodeOver.Parent != null) { - var treeNodeInfo = getTreeNodeInfoForData(nodeOver.Parent.Tag); + TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(nodeOver.Parent.Tag); if (treeNodeInfo.CanInsert != null && treeNodeInfo.CanInsert(nodeDragging.Tag, nodeOver.Tag)) { nodeDropTarget = nodeOver.Parent; @@ -293,7 +298,7 @@ && offsetY > nodeOver.Bounds.Height - nodeOver.Bounds.Height/3 && nodeDragging.PrevNode != nodeOver) { - var treeNodeInfo = getTreeNodeInfoForData(nodeOver.Parent.Tag); + TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(nodeOver.Parent.Tag); if (treeNodeInfo.CanInsert != null && treeNodeInfo.CanInsert(nodeDragging.Tag, nodeOver.Tag)) { nodeDropTarget = nodeOver.Parent; Index: Core/Common/src/Core.Common.Controls.TreeView/TreeViewControl.cs =================================================================== diff -u -ra0688c8ec20cdc107412deaecf9a38a4c1bd5101 -r514d2e7d8903b5846e71ce5e066f574f89f1bb2b --- Core/Common/src/Core.Common.Controls.TreeView/TreeViewControl.cs (.../TreeViewControl.cs) (revision a0688c8ec20cdc107412deaecf9a38a4c1bd5101) +++ Core/Common/src/Core.Common.Controls.TreeView/TreeViewControl.cs (.../TreeViewControl.cs) (revision 514d2e7d8903b5846e71ce5e066f574f89f1bb2b) @@ -501,11 +501,11 @@ private void RefreshChildNodes(TreeNode treeNode, TreeNodeInfo treeNodeInfo) { var newTreeNodes = new Dictionary(); - var outdatedTreeNodes = treeNode.Nodes.Cast().ToList(); - var currentTreeNodesPerTag = treeNode.Nodes.Cast().ToList().ToDictionary(ctn => ctn.Tag, ctn => ctn); - var newChildNodeObjects = treeNodeInfo.ChildNodeObjects != null - ? treeNodeInfo.ChildNodeObjects(treeNode.Tag) - : new object[0]; + List outdatedTreeNodes = treeNode.Nodes.Cast().ToList(); + Dictionary currentTreeNodesPerTag = outdatedTreeNodes.ToDictionary(ctn => ctn.Tag, ctn => ctn); + object[] newChildNodeObjects = treeNodeInfo.ChildNodeObjects != null + ? treeNodeInfo.ChildNodeObjects(treeNode.Tag) + : new object[0]; // Create a list of outdated tree nodes and new tree nodes for (var i = 0; i < newChildNodeObjects.Length; i++) @@ -537,6 +537,11 @@ } // If relevant, set selection to the last of the added nodes + SelectLastNewNode(newTreeNodes); + } + + private void SelectLastNewNode(Dictionary newTreeNodes) + { var lastAddedNodeToSetSelectionTo = newTreeNodes.Values.LastOrDefault(node => { var dataObject = node.Tag;