【问题标题】:TreeView not visually updating while right mouse dragging鼠标右键拖动时 TreeView 没有视觉更新
【发布时间】:2014-03-24 15:11:40
【问题描述】:

我有一个 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;
    }

【问题讨论】:

  • 什么都没有跳出来,用鼠标右键D+D没问题。我假设 DragOver 事件处理程序没有运行。看不到 DragEnter,e.Effect 分配很可能是问题所在。注意异常,它们会被 D+D 事件处理程序吞没。
  • 这很奇怪。单步执行代码,我看到节点被选中。当 DragDrop 发生时,节点被选中。只要按住鼠标右键,控件就不会在视觉上更新。编辑:我也尝试过使用相同的效果,没有任何变化。

标签: c# treeview


【解决方案1】:

我自己也遇到了这个问题,并且进行了本地发送消息调用以强制选择项目对我有用:

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多