我有一个TreeView控件,我已经实现了拖放。DragOver处理程序中有一些代码可以突出显示被拖动节点的正确目标节点,这很好地工作了。我使用鼠标左键来移动节点,使用鼠标右键来复制节点。问题是,当使用右键时,TreeView在拖动操作期间不能正确显示所选节点。正在选择适当的节点,我已经用停止点验证了这一点,但TreeView本身没有显示这一点。当使用鼠标左键时,它会显示它。
private void DocumentMap_ItemDrag(object sender, ItemDragEventArgs e)
{
// Only handle TreeNode objects
if (e.Item.GetType() != typeof(TreeNode)) return;
this.dragNode = e.Item as TreeNode;
var sourceType = XmlItem.FromElement(this.dragNode.Tag as XElement).ItemType;
if (sourceType == Xml.ProjectHeader || sourceType == Xml.GroupHeader) return;
switch (e.Button)
{
case System.Windows.Forms.MouseButtons.Left:
DoDragDrop(e.Item, DragDropEffects.Move);
break;
case System.Windows.Forms.MouseButtons.Right:
DoDragDrop(e.Item, DragDropEffects.Copy);
break;
}
this.dragNode = null;
}
private void DocumentMap_DragOver(object sender, DragEventArgs e)
{
if (this.dragNode == null) return;
var targetType = XmlItem.FromNode(this.dragNode.Parent).ItemType;
var hoverNode = DocumentMap.GetNodeAt(DocumentMap.PointToClient(new Point(e.X, e.Y)));
var targetNode = FindNodeInAncestors(hoverNode, targetType);
if (targetNode != null && targetNode != this.dragNode.Parent)
DocumentMap.SelectedNode = targetNode;
else
DocumentMap.SelectedNode = null;
}
我自己也遇到过这个问题,使用本地send消息调用来强制项目选择对我有效:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public static class NativeExtensions
{
private const int TVM_SELECTITEM = (0x1100 + 11);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, IntPtr wParam, IntPtr lParam);
/// <summary>
/// Forces the selection of this <see cref="System.Windows.Forms.TreeNode"/> using an unsafe SendMessage call
/// </summary>
/// <param name="selectionType">Type of selection to make</param>
/// <exception cref="System.NullReferenceException">This node is null</exception>
/// <exception cref="System.ArgumentException">The handle for this node is not created, the node does
/// not have a parent <see cref="System.Windows.Forms.TreeView"/>, or the handle for the node's parent <see cref="System.Windows.Forms.TreeView"/>
/// is not created</exception>
public static void ForceSelection(this TreeNode nodeToSelect, UnmanagedTreeNodeSelectType selectionType)
{
if (nodeToSelect == null)
throw new NullReferenceException();
if (nodeToSelect.Handle == IntPtr.Zero)
throw new ArgumentException("Handle for node is not created");
if (nodeToSelect.TreeView == null)
throw new ArgumentException("Node does not have a parent TreeView.");
if (nodeToSelect.TreeView.Handle == IntPtr.Zero)
throw new ArgumentException("Handle for node's parent TreeView is not created.");
nodeToSelect.TreeView.SelectedNode = nodeToSelect;
SendMessage(new HandleRef(nodeToSelect.TreeView, nodeToSelect.TreeView.Handle), TVM_SELECTITEM, (IntPtr)selectionType, nodeToSelect.Handle);
}
/// <summary>
/// Type of selection to make when forcing a <see cref="System.Windows.Forms.TreeNode"/> selection with unmanaged code
/// </summary>
public enum UnmanagedTreeNodeSelectType
{
//Documentation taken from http://msdn.microsoft.com/en-us/library/31917zyz.aspx
/// <summary>
/// Sets the selection to the given item
/// </summary>
SetSelection = 0x0009, //TVGN_CARET
/// <summary>
/// Redraws the given item in the style used to indicate the target of a drag-and-drop operation
/// </summary>
DragAndDropTarget = 0x0008, //TVGN_DROPHILITE
/// <summary>
/// Scrolls the tree view vertically so that the given item is the first visible item
/// </summary>
FirstVisible = 0x0005, //TVGN_FIRSTVISIBLE
}
}
使用它:
targetNode.ForceSelection(NativeExtensions.UnmanagedTreeNodeSelectType.DragAndDropTarget);