Index: Core/Common/src/Core.Common.Controls.TreeView/DragDropHandler.cs =================================================================== diff -u -red0efdcfe1c041f58f65ac59a18c42bd1df9f1ff -r7b47bd7322094ce1af65e2d69ccc154d58d297e6 --- Core/Common/src/Core.Common.Controls.TreeView/DragDropHandler.cs (.../DragDropHandler.cs) (revision ed0efdcfe1c041f58f65ac59a18c42bd1df9f1ff) +++ Core/Common/src/Core.Common.Controls.TreeView/DragDropHandler.cs (.../DragDropHandler.cs) (revision 7b47bd7322094ce1af65e2d69ccc154d58d297e6) @@ -62,7 +62,7 @@ var point = treeView.PointToClient(new Point(e.X, e.Y)); TreeNode nodeOver = treeView.GetNodeAt(point); - var draggedNode = (TreeNode) e.Data.GetData(typeof(TreeNode)); + var draggedNode = GetDraggedNodeData(e); if (nodeOver == null) { @@ -107,18 +107,18 @@ var point = treeView.PointToClient(lastDragOverPoint); TreeNode nodeOver = treeView.GetNodeAt(point); - var draggedNode = (TreeNode) e.Data.GetData(typeof(TreeNode)); + var draggedNode = GetDraggedNodeData(e); - if (nodeOver == null || draggedNode == null || nodeOver == draggedNode || IsDropTargetChildOfDraggedNode(nodeOver, draggedNode)) + if (draggedNode == null || nodeOver == null || nodeOver == draggedNode || IsDropTargetChildOfDraggedNode(nodeOver, draggedNode)) { RemovePlaceHolder(treeView); - + e.Effect = DragDropEffects.None; return; } ScrollIntoView(point, nodeOver, treeView); - PlaceholderLocation placeholderLocation = GetPlaceHoldersLocation(treeView, draggedNode, nodeOver, e, getTreeNodeInfoForData); + PlaceholderLocation placeholderLocation = GetPlaceHoldersLocation(treeView, draggedNode, nodeOver, getTreeNodeInfoForData); if (nodeDropTarget == null) { @@ -132,6 +132,9 @@ if (placeholderLocation == PlaceholderLocation.None) { + RemovePlaceHolder(treeView); + e.Effect = DragDropEffects.None; + return; } @@ -147,6 +150,18 @@ } } + private static TreeNode GetDraggedNodeData(DragEventArgs e) + { + try + { + return (TreeNode) e.Data.GetData(typeof(TreeNode)); + } + catch (InvalidCastException) + { + return null; + } + } + /// /// This method handles the event for a . /// @@ -265,7 +280,7 @@ } } - private PlaceholderLocation GetPlaceHoldersLocation(FormsTreeView treeView, TreeNode nodeDragging, TreeNode nodeOver, DragEventArgs e, Func getTreeNodeInfoForData) + private PlaceholderLocation GetPlaceHoldersLocation(FormsTreeView treeView, TreeNode nodeDragging, TreeNode nodeOver, Func getTreeNodeInfoForData) { var placeholderLocation = PlaceholderLocation.None; int offsetY = treeView.PointToClient(Cursor.Position).Y - nodeOver.Bounds.Top; @@ -275,7 +290,7 @@ if (nodeOver.Parent != null) { TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(nodeOver.Parent.Tag); - if (treeNodeInfo.CanInsert != null && treeNodeInfo.CanInsert(nodeDragging.Tag, nodeOver.Tag)) + if (treeNodeInfo.CanInsert != null && treeNodeInfo.CanInsert(nodeDragging.Tag, nodeOver.Parent.Tag)) { nodeDropTarget = nodeOver.Parent; dropAtLocation = nodeOver.Parent == null ? 0 : nodeOver.Parent.Nodes.IndexOf(nodeOver); @@ -300,7 +315,7 @@ && nodeDragging.PrevNode != nodeOver) { TreeNodeInfo treeNodeInfo = getTreeNodeInfoForData(nodeOver.Parent.Tag); - if (treeNodeInfo.CanInsert != null && treeNodeInfo.CanInsert(nodeDragging.Tag, nodeOver.Tag)) + if (treeNodeInfo.CanInsert != null && treeNodeInfo.CanInsert(nodeDragging.Tag, nodeOver.Parent.Tag)) { nodeDropTarget = nodeOver.Parent; dropAtLocation = nodeOver.Parent != null @@ -324,13 +339,6 @@ placeholderLocation = PlaceholderLocation.Middle; } - if (placeholderLocation == PlaceholderLocation.None - || (placeholderLocation == PlaceholderLocation.Middle && nodeDropTarget == nodeDragging.Parent)) - { - RemovePlaceHolder(treeView); - e.Effect = DragDropEffects.None; - } - return placeholderLocation; } Index: Core/Common/test/Core.Common.Controls.TreeView.Test/DragDropHandlerTest.cs =================================================================== diff -u -rc8813d252befec1494a76e44e04b64985b34d7fc -r7b47bd7322094ce1af65e2d69ccc154d58d297e6 --- Core/Common/test/Core.Common.Controls.TreeView.Test/DragDropHandlerTest.cs (.../DragDropHandlerTest.cs) (revision c8813d252befec1494a76e44e04b64985b34d7fc) +++ Core/Common/test/Core.Common.Controls.TreeView.Test/DragDropHandlerTest.cs (.../DragDropHandlerTest.cs) (revision 7b47bd7322094ce1af65e2d69ccc154d58d297e6) @@ -1,6 +1,9 @@ using System; +using System.Drawing; +using System.IO; using System.Windows.Forms; using NUnit.Framework; +using Rhino.Mocks; namespace Core.Common.Controls.TreeView.Test { @@ -47,5 +50,113 @@ // Assert Assert.IsNull(treeView.SelectedNode); } + + [Test] + [TestCase(false, DragDropEffects.None)] + [TestCase(true, DragDropEffects.Move)] + public void HandleDragOver_TreeNodeDraggedToDroppableNode_DragDropEffectSetForEvent(bool canDrop, DragDropEffects dropEffect) + { + // Setup + int targetHeight = 30; + + var mocks = new MockRepository(); + var data = mocks.Stub(); + var treeView = mocks.Stub(); + var treeNode = mocks.Stub(); + var graphicsMock = mocks.Stub(); + treeNode.Stub(tn => tn.Parent).Return(null); + treeNode.Stub(tn => tn.Bounds).Return(new Rectangle(0, 0, 50, targetHeight)); + + var draggingNode = new TreeNode("DraggingNode"); + var nodePoint = new Point(0, 10); + + data.Expect(d => d.GetData(d.GetType())).IgnoreArguments().Return(draggingNode); + treeView.Stub(tv => tv.PointToClient(Point.Empty)).IgnoreArguments().Return(nodePoint); + treeView.Stub(tv => tv.GetNodeAt(nodePoint)).Return(treeNode); + treeView.Stub(tv => tv.CreateGraphics()).Return(graphicsMock); + mocks.ReplayAll(); + + Func action = o => new TreeNodeInfo + { + CanDrop = (oo,op) => canDrop + }; + DragDropHandler ddh = new DragDropHandler(); + DragEventArgs dragEvent = new DragEventArgs(data, 0, 10, 15, DragDropEffects.All, DragDropEffects.None); + + // Call + ddh.HandleDragOver(treeView, dragEvent, action); + + // Assert + Assert.AreEqual(dragEvent.Effect, dropEffect); + mocks.VerifyAll(); + } + + [Test] + public void HandleDragOver_NoTreeNodeDraggedToDroppableNode_DragDropEffectNoneSetForEvent() + { + // Setup + int targetHeight = 30; + + var mocks = new MockRepository(); + var data = mocks.Stub(); + var treeView = mocks.Stub(); + var treeNode = mocks.Stub(); + var graphicsMock = mocks.Stub(); + treeNode.Stub(tn => tn.Parent).Return(null); + treeNode.Stub(tn => tn.Bounds).Return(new Rectangle(0, 0, 50, targetHeight)); + + var nodePoint = new Point(0, 10); + + data.Expect(d => d.GetData(d.GetType())).IgnoreArguments().Return(new object()); + treeView.Stub(tv => tv.PointToClient(Point.Empty)).IgnoreArguments().Return(nodePoint); + treeView.Stub(tv => tv.GetNodeAt(nodePoint)).Return(treeNode); + treeView.Stub(tv => tv.CreateGraphics()).Return(graphicsMock); + mocks.ReplayAll(); + + Func action = o => new TreeNodeInfo(); + DragDropHandler ddh = new DragDropHandler(); + DragEventArgs dragEvent = new DragEventArgs(data, 0, 10, 15, DragDropEffects.All, DragDropEffects.None); + + // Call + ddh.HandleDragOver(treeView, dragEvent, action); + + // Assert + Assert.AreEqual(dragEvent.Effect, DragDropEffects.None); + mocks.VerifyAll(); + } + + [Test] + public void HandleDragOver_DataDraggedThrowsInvalidCastException_DragDropEffectNoneSetForEvent() + { + // Setup + int targetHeight = 30; + + var mocks = new MockRepository(); + var data = mocks.Stub(); + var treeView = mocks.Stub(); + var treeNode = mocks.Stub(); + var graphicsMock = mocks.Stub(); + treeNode.Stub(tn => tn.Parent).Return(null); + treeNode.Stub(tn => tn.Bounds).Return(new Rectangle(0, 0, 50, targetHeight)); + + var nodePoint = new Point(0, 10); + + data.Expect(d => d.GetData(d.GetType())).IgnoreArguments().Throw(new InvalidCastException()); + treeView.Stub(tv => tv.PointToClient(Point.Empty)).IgnoreArguments().Return(nodePoint); + treeView.Stub(tv => tv.GetNodeAt(nodePoint)).Return(treeNode); + treeView.Stub(tv => tv.CreateGraphics()).Return(graphicsMock); + mocks.ReplayAll(); + + Func action = o => new TreeNodeInfo(); + DragDropHandler ddh = new DragDropHandler(); + DragEventArgs dragEvent = new DragEventArgs(data, 0, 10, 15, DragDropEffects.All, DragDropEffects.None); + + // Call + ddh.HandleDragOver(treeView, dragEvent, action); + + // Assert + Assert.AreEqual(dragEvent.Effect, DragDropEffects.None); + mocks.VerifyAll(); + } } } \ No newline at end of file