【问题标题】:treeview drag-drop effect not working树视图拖放效果不起作用
【发布时间】:2015-12-21 14:37:57
【问题描述】:

我似乎遇到了一些问题。我有一个表格,上面有一个树视图。在此树视图中,有“文件夹”和“项目”。我允许用户移动文件夹和项目的节点/更改层次结构。

我试图在拖放操作生效时更改鼠标光标,但这似乎不起作用。我已经更改了所有必要的值,以及在不同事件期间的鼠标光标,但无济于事。

下面的代码中是否缺少某些会妨碍正确行为的内容?基本上,显示的光标始终是默认的拖放光标(移动、复制等)...请注意,我还在树视图上启用了 HotTracking 以启用 GiveFeedback 并触发/命中断点。

[编辑] -- 感谢 Hans 的解决方案。基本上,DoDragDrop 调用必须通过使用其 FQN 来定位您想要的控件。如果您的源代码控制是触发 ItemDrag 事件的源代码控制,则无关紧要,您必须明确指定它。请参阅下面更新的代码。

        #region Drag and Drop Methods and Event Handlers
        /// <summary>
        /// Performs the necessary actions when the user drags and drops a node around the treeview.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tv_Terms_DragDrop(object sender, DragEventArgs e)
        {
            // Retrieve the client coordinates of the drop location.
            Point targetPoint = this.tv_Terms.PointToClient(new Point(e.X, e.Y));

            // Retrieve the node at the drop location.
            TreeNode targetNode = this.tv_Terms.GetNodeAt(targetPoint);

            // confirm that the target node isn't null
            // (for example if you drag outside the control)
            if (targetNode != null)
            {

                // Retrieve the node that was dragged.
                TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
                TreeNode draggedParentNode = draggedNode.Parent;

                //PERFORM DB OPERATIONS HERE>>

                // Expand the node at the location 
                // to show the dropped node.
                targetNode.Expand();
            }
        }

        /// <summary>
        /// Adds the necessary effect when dragging.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tv_Terms_ItemDrag(object sender, ItemDragEventArgs e)
        {
            this.tv_Terms.DoDragDrop(e.Item, DragDropEffects.Move);
        }

        /// <summary>
        /// Adds the necessary effect when dragging.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tv_Terms_DragEnter(object sender, DragEventArgs e)
        {
            if(e.Data.GetDataPresent(typeof(TreeNode)) == true)
                e.Effect = DragDropEffects.Move;
        }

        /// <summary>
        /// Selects the appropriate node when the user is dragging an item.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tv_Terms_DragOver(object sender, DragEventArgs e)
        {
            //THIS METHOD AUTO-SCROLLS THE TREEVIEW IF YOU REACH THE EDGES...
            this.tv_Terms.Scroll();
            TreeNode node = this.tv_Terms.GetNodeAt(this.tv_Terms.PointToClient(new Point(e.X, e.Y)));
            if (node != null)
            {
                NodeInfo info = node.Tag as NodeInfo;

                if (!info.IsContainer)
                    node = node.Parent;

                this.tv_Terms.SelectedNode = node;
            }
        }

        private void tv_Terms_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            //I DON'T CARE WHAT TYPE OF DRAG IT IS, ALWAYS USE THE CUSTOM CURSOR.
            e.UseDefaultCursors = false;
            Cursor.Current = lastcursor;                
        }

        //I SET/CACHE THE MOUSE CURSOR HERE
        private void tv_Terms_MouseDown(object sender, MouseEventArgs e)
        {
            TreeNode node = this.tv_Terms.GetNodeAt(e.X, e.Y);
            if (node != null)
            {
                //THIS METHOD CREATES THE CUSTOM CURSOR.
                Bitmap curs = Helpers.CreateNodeCursorIcon(this.imageList1.Images[node.ImageIndex], node.Text);
                this.lastcursor = new Cursor(curs.GetHicon());
                //I CONFIRM THE PROPER CURSOR BY PLACING THE IMAGE IN A P.B.
                this.pictureBox1.Image = curs;
                Cursor.Current = lastcursor;
            }

        }

        #endregion

【问题讨论】:

    标签: c# winforms treeview


    【解决方案1】:
        DoDragDrop(e.Item, DragDropEffects.Move);
    

    这是您的 tv_Terms_ItemDrag() 方法中的一个细微错误,它使用 form 的 DoDragDrop() 方法。这对您来说很重要,GiveFeedback 事件是在 拖动源 上触发的,而不是在放置目标上触发的。换句话说,您的 GiveFeedback 事件永远不会触发。顺便说一句,调试器很容易看到,只需在事件处理程序上设置一个断点,就可以看到它永远不会运行。修复:

        private void tv_Terms_ItemDrag(object sender, ItemDragEventArgs e)
        {
            tv_Terms.DoDragDrop(e.Item, DragDropEffects.Move);
        }
    

    此方法最好也是您要创建光标的方法。而且您应该在 DragEnter 事件处理程序中更具辨别力,因此它不允许丢弃 everything,请使用 e.Data.GetDataPresent(typeof(TreeNode)) 进行验证。并移除 DragOver 中的光标操作。

    【讨论】:

    • 奇怪的是,GiveFeedback 确实会触发...但我会尝试在 ItemDrag 中指定树视图,看看是否可以。
    • 哦……我的……天哪!太感谢了!我还在 DragEnter 中添加了检查(有意义!)...请参阅更新的问题帖子。万分感谢! :)
    • 还有一件事:我要在哪里使光标恢复正常?
    • 引用:“并删除 DragOver 中的光标操作”。你一直在破解它试图让它工作,发现它没有效果,忘记再次删除它。 this.Cursor 赋值防止光标恢复正常。
    猜你喜欢
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多