winform上控件的拖拽小結


這里羅列出幾個相關的事件和屬性,具體的實現介紹已有非常優秀的文章了,文章末尾我將會給出,大家可以去參考。

屬性:

AllowDrop: 目標控件必須設定為true,才能接受拖拽來的東西。

事件:

ItemDrag: 源控件在拖動開始時發生。在這里需調用DoDragDrop方法開始拖拽行為。

DragEnter:目標控件接受到拖拽行為時發生。在這里可以通過e.Effect設定目標控件能接受的拖拽行為。

DragOver:目標控件接受到拖拽行為時不間斷發生。在DragEnter后觸發。這里不可做耗時操作。

DragLeave:拖拽離開目標控件后觸發。

DragDrop:拖拽開始后,在目標控件上松開鼠標時觸發。

比如把一個ListView(A)的ListViewItem拖拽到TreeView(B)上的需要完成的步驟如下。

1,設置B的AllowDrop=true;

2,需要添加的事件和事件執行順序如下:

有“放”操作時:ItemDrag(A)→DragEnter(B)→DragOver(B)→DragDrop(B) 

沒有“放”操作時:ItemDrag(A)→DragEnter(B)→DragOver(B)→DragLeave(B) 

下面給一個簡單的實現,並實現高亮顯示treeview節點:

        // listview
        private void fileView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            var item = e.Item as ListViewItem;

            (sender as ListView).DoDragDrop(item.Tag as string, DragDropEffects.Copy);
        }

        // treeview
        private void folderView_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.Text))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }

        private void folderView_DragOver(object sender, DragEventArgs e)
        {
            var location = this.folderView.PointToClient(new Point(e.X, e.Y));
            var node = this.folderView.GetNodeAt(location);
            if (node == null) return;
            if (node.PrevVisibleNode != null)
            {
                node.PrevVisibleNode.BackColor = node.TreeView.BackColor;
                node.PrevVisibleNode.ForeColor = node.TreeView.ForeColor;
            }
            if (node.NextVisibleNode != null)
            {
                node.NextVisibleNode.BackColor = node.TreeView.BackColor;
                node.NextVisibleNode.ForeColor = node.TreeView.ForeColor;
            }
            node.BackColor = SelectedBackColor; ;
            node.ForeColor = SelectedForeColor;
        }

        private void folderView_DragDrop(object sender, DragEventArgs e)
        {
            var abc = e.Data.GetData(DataFormats.Text);
            var location = this.folderView.PointToClient(new Point(e.X, e.Y));
            var node = this.folderView.GetNodeAt(location.X, location.Y);
            // do something...
            ClearTreeNodesDragColor(this.folderView.Nodes);
        }
        private void ClearTreeNodesDragColor(TreeNodeCollection treeNodes)
        {
            foreach (TreeNode node in treeNodes)
            {
                if (!node.IsVisible)
                    continue;
                node.BackColor = node.TreeView.BackColor;
                node.ForeColor = node.TreeView.ForeColor;
                ClearTreeNodesDragColor(node.Nodes);
            }
        }
        private void folderView_DragLeave(object sender, EventArgs e)
        {
            ClearTreeNodesDragColor(this.folderView.Nodes);
        }

 

上面的代碼功能不完全,要實現如拖動時顯示圖標,以及桌面和應用程序之間的互相拖動可以參看下面的幾篇文章,這要求有一定的WindowsAPI編程經驗,供大家參考吧。

2014/12/03:

看回復中有需求要實現TabControl的拖動,網上查了下,需要重寫TabControl的部分事件,但並不是很復雜。

下面給出一個實現,親測可以使用。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace WindowsFormsApplication1
{
    public class DragableTabControl : TabControl
    {
        public DragableTabControl()
        {
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            TabPage tabPage = GetTabPageByTab(new Point(e.X, e.Y));
            if (tabPage != null)
            {
                this.DoDragDrop(tabPage, DragDropEffects.All);
            }
        }

        private TabPage GetTabPageByTab(Point point)
        {
            for (int i = 0; i < this.TabPages.Count; i++)
            {
                if (GetTabRect(i).Contains(point))
                {
                    return this.TabPages[i];
                }
            }
            return null;
        }

        protected override void OnDragOver(DragEventArgs e)
        {
            base.OnDragOver(e);
            TabPage source = (TabPage)e.Data.GetData(typeof(TabPage));
            if (source != null)
            {
                TabPage target = GetTabPageByTab(PointToClient(new Point(e.X, e.Y)));
                if (target != null)
                {
                    e.Effect = DragDropEffects.Move;
                    MoveTabPage(source, target);
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void MoveTabPage(TabPage source, TabPage target)
        {
            if (source == target)
                return;

            int targetIndex = -1;
            List<TabPage> lstPages = new List<TabPage>();
            for (int i = 0; i < this.TabPages.Count; i++)
            {
                if (this.TabPages[i] == target)
                {
                    targetIndex = i;
                }
                if (this.TabPages[i] != source)
                {
                    lstPages.Add(this.TabPages[i]);
                }
            }
            this.TabPages.Clear();
            this.TabPages.AddRange(lstPages.ToArray());
            this.TabPages.Insert(targetIndex, source);
            this.SelectedTab = source;
        }
    }
}

 

唯一的不足,可能是點擊TabPage是,會有拖拽的虛線框,但不影響使用。

 

.NET中的Drag and Drop操作(一) 

http://www.codeproject.com/Articles/15059/C-File-Browser


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM