winform上控件的拖拽小结
2014-10-14 15:25 xiashengwang 阅读(11645) 评论(2) 编辑 收藏 举报这里罗列出几个相关的事件和属性,具体的实现介绍已有非常优秀的文章了,文章末尾我将会给出,大家可以去参考。
属性:
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是,会有拖拽的虚线框,但不影响使用。