DataGridView拖动到TreeView

很多时候我们会有这样的需求:一个窗体中有两个GRID,两个GRID中数据表结构差不多,我们要把一个GRID中的数据加入到另一个GRID中。一般的做法是新增一个导入或导出按钮,选择目标行后,通过按钮来触发事件,实现两个GRID中数据的增减。

嘿嘿,但是,如果我们能够在选中目标行后,直接用鼠标将选中的行拖拽到另一个GRID中是不是比较酷一点呢。

下面,我们就来看看如何实现它。

首先,创建示例数据。

我们还是用上一节:玩转DataGridView之行的展开与收缩的数据脚本,再用它新建两张表就行。

select * into Department_A from Department where DparentId=1
select * into Department_B from Department where DparentId=2

说一下思路:我们要实现的效果是在源Grid中选中行后,按住鼠标左键不放,将选中的行从源Grid中拖出,拖入到目标Grid中。其中所作的动作有四个:

1.选中行(可以单行或多行)

2.拖拽行

3.从源Grid中移除选中行(其实也可以不移除,看实际需求了,本例中将行从Grid中移除了)

4.目标Grid中新增选中行。

我们来一一分析。我在项目中建了两个Grid:sourceGrid即源,targetGrid即目标。

1.选中行

我们必需先要有一个全局变量来保存选中的行。

private DataGridViewSelectedRowCollection sourceRowCollection = null;//用来保存选中的行

给sourceRowCollection赋值当然是在sourceGrid_MouseDown事件中了。这里我们还必需要保证鼠标点击在有效区域才能给sourceRowCollection赋值。

这里有用到一个类HitTestInfo,NND,不知道微软为什么这样命名,害我找了很久。这个类可以获取当前鼠标所在的RowIndex和ColumnIndex

 private void sourceGrid_MouseDown(object sender, MouseEventArgs e)
        {
            //捕获鼠标点击区域的信息
            DataGridView.HitTestInfo hitTestInfo= this.sourceGrid.HitTest(e.X, e.Y);

            if (e.X < 30 && hitTestInfo.RowIndex > -1)
            {
                if (this.sourceGrid.SelectedRows.Count > 0)
                {
                    sourceRowCollection = this.sourceGrid.SelectedRows;
                }
            }
            else
                sourceRowCollection = null;
        }

2.拖拽行

拖拽行就要用到一个很重要的方法:DoDragDrop,它有参数,一个是要拖拽的数据,一个要实现的效果。重要的是调用了后DoDragDrop可以触发目标控件(本例中是targetGrid)的DragOver、DragDrop等事件。当然前提是你的目标控件的AllowDrop为True。我之前就是因为AllowDrop没有设置为true,没有触发DragOver事件,害我瞎找了好久的原因。

关于DoDragDrop,参考:http://msdn.microsoft.com/zh-cn/library/ie/system.windows.forms.control.dodragdrop.aspx这里更详细的介绍,也有一个很好的例子。

我们在sourceGrid_MouseMove中去调用DoDragDrop方法:

 private void sourceGrid_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (sourceRowCollection != null)
                {
                    DragDropEffects effect = this.sourceGrid.DoDragDrop(sourceRowCollection, DragDropEffects.Move);
                    if (effect == DragDropEffects.Move)
                    {
                        //在sourceGrid中移除选中行
                        foreach (DataGridViewRow row in sourceRowCollection)
                        {
                            this.sourceGrid.Rows.Remove(row);
                        }
                        //将sourceRowCollection重新置空
                        sourceRowCollection = null;
                    }
                }
            }
        }

注意:effect == DragDropEffects.Move会在目标控件的DragDrop等事件执行完后再执行。
移动到目标窗体时,会触发targetGrid_DragOver事件,我们在这里设置DragDropEffects的值.

private void targetGrid_DragOver(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent(typeof(DataGridViewSelectedRowCollection)))
            {

                e.Effect = DragDropEffects.None;
                return;
            }
            else
            {
                e.Effect = DragDropEffects.Move;  //这个值会返回给DoDragDrop方法
            }
        }

拖拽完成时,会触发DragDrop,我们在这里将拖拽的行赋给targetGrid

3.从源Grid中移除选中行

移除选中行已经在sourceGrid_MouseMove事件中了,即:

if (effect == DragDropEffects.Move)
                    {
                        //在sourceGrid中移除选中行
                        foreach (DataGridViewRow row in sourceRowCollection)
                        {
                            this.sourceGrid.Rows.Remove(row);
                        }
                        //将sourceRowCollection重新置空
                        sourceRowCollection = null;
                    }

4.目标Grid中新增选中行

新增行的代码也在targetGrid_DragDrop中,因为这个在拖拽完成时触发。这里我们分新增与插入的情况,详见上面的代码。

最后说明一下,我只做了界面上的两个GRID中数据的增减,并没有将更改保存到数据库中,大家有兴趣的可以自己去实现一下。

PS:貌似同一个窗体中的两个GRID不能有相同的列名,这点微软的做法让我很不爽,绑定数据的时候我不得不多写一个方法。

源代码:DataGridDemo,拖拽窗体即项目中的MoveGridForm

时间: 2024-10-28 14:09:11

DataGridView拖动到TreeView的相关文章

S2---深入.NET平台和C#编程的完美总结

1.NET简单解说 l 面向对象提升 OOP(Object Oriented  Programming)面向对象编程 AOP:(Aspache  Oriented Programming):面向切面编程 OOD(Object Oriented  Designer)面向对象设计(架构师)   3万/month OOA(Object Oriented  Analysis)面向对象分析  (分析师) 10万/month DBA(Database Administrator,简称DBA) l 泛型集合对

分享两种实现Winform程序的多语言支持的解决方案

因公司业务需要,需要将原有的ERP系统加上支持繁体语言,但不能改变原有的编码方式,即:普通程序员感受不到编码有什么不同.经过我与几个同事的多番沟通,确定了以下两种方案: 方案一:在窗体基类中每次加载并显示窗体时,会自动递归遍历含文本显示的控件(Button,CheckBox,GroupBox,Label,LinkLabel,TextBox,StatusStrip,TabPage,ToolStrip,RadioButton,DateTimePicker,DataGridView,CheckedLi

Blend 修改TreeViewItem样式

1.用Blend for Visual Studio 2019 新建Wpf项目,拖动一个TreeView控件到Grid上 <Grid> <TreeView> <TreeViewItem Header="TreeViewItem"> <TreeViewItem Header="TreeViewItem"/> </TreeViewItem> <TreeViewItem Header="TreeV

WinForm中TreeView控件实现鼠标拖动节点(可实现同级节点位置互换,或拖到目标子节点)

private int draptype=1;//1:不同级, 不为1:拖同级 private void treeView1_ItemDrag(object sender, ItemDragEventArgs e) { if (e.Button == MouseButtons.Left) { DoDragDrop(e.Item, DragDropEffects.Move); } } private void treeView1_DragEnter(object sender, DragEvent

实现DataGridView行的拖动,即实现行的顺序交换

参考:http://blog.csdn.net/soarheaven/article/details/3267379 1.界面准备 (1)首先在form中添加一个DataGridView控件,将默认AllowDrop=false 的属性设置为True,否侧不能拖动! (2)对DataGridView的对象实现非数据源的绑定,因为设置DataSource属性即当控件被数据绑定时,无法以编程方式向 DataGridView 的行集合中添加行. 2.代码准备 (1)控制移动时鼠标的图形,否则是一个禁止

Winform TreeView 节点拖动

private void treeView_ItemDrag(object sender, ItemDragEventArgs e) { TreeNode dragNode = e.Item as TreeNode; DoDragDrop(dragNode, DragDropEffects.Move); } private void treeView_DragEnter(object sender, DragEventArgs e) { e.Effect = e.AllowedEffect; }

DevExpress WinForm GridControl 实现拖动多行到TreeView

参考文章:Drag-and-drop of multiple selected grid rows 如果列表有使用行内编辑功能,需要将列表的 OptionsBehavior.EditorShowMode 属性设置为 MouseUp 或者 Click        private GridHitInfo downHitInfo = null; private void myView_MouseDown(object sender, MouseEventArgs e) { GridView view

ListView、TreeView和DataGrid。

原文:ListView.TreeView和DataGrid. 1.ListView. ListView继承自简单的没有特色的ListBox,并使用View属性进行扩展.增加了对基于列显示的支持,并增加了快速切换视图或显示模式的能力,而不需要重新绑定数据以及重新构建列表.其中View属性是是一个扩展点,用于创建内容丰富的列表,如果没有设置View属性,ListView控件的行为就类似于功能较少的祖先ListBox控件的行为.ListView目前只提供了GridView视图,用于创建多列是非常有用的

DataGridView滚动慢?的解决方法

当DataGridView达到一定大小的时候,拖动滚动条就会非常慢,出现让人难以忍受的闪动. 即便只有100行,每行30列. 解决方法是启用DataGridView的双缓冲. 1 2 3 4 5 6 7 8 9 10 11 12 public static class ExtensionMethods {     public static void DoubleBuffered(this DataGridView dgv, bool setting)     {         Type dg