Эффект перетаскивания дерева не работает

Кажется, у меня проблема. У меня есть форма, на которой есть дерево. В этом дереве есть "папки" и "элементы". Я разрешаю пользователю перемещать узлы/изменять иерархию для обеих папок и элементов.

Я пытаюсь изменить курсор мыши, когда действует операция перетаскивания, однако это просто не работает. Я изменил все необходимые значения и указатель мыши во время различных событий, но безрезультатно.

Есть ли что-то в коде ниже, что предотвратит правильное поведение? В принципе, отображаемый курсор всегда является указателем перетаскивания по умолчанию (перемещение, копирование и т.д.). Обратите внимание, что я также включил HotTracking в древовидной структуре, чтобы включить GiveFeedback, и он запускает/удаляет точку останова.

[EDIT] - Спасибо Гансу за решение. В принципе, вызов 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

Ответ 1

    DoDragDrop(e.Item, DragDropEffects.Move);

Это тонкая ошибка в вашем tv_Terms_ItemDrag(), она использует метод DoDragDrop() формы. Это важно в вашем случае, событие GiveFeedback запускается в источнике перетаскивания, а не в целевой точке. Другими словами, событие GiveFeedback никогда не срабатывает. Легко видеть с помощью отладчика btw, просто установите точку останова на обработчике событий, чтобы увидеть, что он никогда не запускается. Fix:

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

Этот метод предпочтительно также является тем, где вы хотите создать курсор. И вы должны быть более различимыми в обработчике событий DragEnter, чтобы он не позволял отбрасывать все, для проверки используйте e.Data.GetDataPresent(typeof (TreeNode)). И удалите манипуляции с курсором в DragOver.