【转】Winform中DataGridView控件实现拖动行,并在拖动状态中目标行上显示一条红线。...

DataGridView拖放功能
本文介绍如何在DataGridView控件中实现行的拖放功能,包括设置允许拖放的属性、响应鼠标事件、开始拖放过程、处理拖放过程中的行重绘以及完成拖放后的逻辑操作。

效果预览:
效果图

首先设置DataGridView控件的AllowDrop属性为True,MultiSelect为False,SelectionMode为FullRowSelect

在窗口类里定义基本的变量:

01// 数据表
02DataTable dataTable = new DataTable();
03// 拖动的源数据行索引
04private int indexOfItemUnderMouseToDrag = -1;
05// 拖动的目标数据行索引
06private int indexOfItemUnderMouseToDrop = -1;
07// 拖动中的鼠标所在位置的当前行索引
08private int indexOfItemUnderMouseOver = -1;
09// 不启用拖放的鼠标范围
10private Rectangle dragBoxFromMouseDown = Rectangle.Empty;


然后在窗口加载时添加示例数据:

01private void MainForm_Load(object sender, EventArgs e)
02{
03    dataTable.Columns.Add("ID", typeof(int));
04    dataTable.Columns.Add("Column1", typeof(string));
05    dataTable.Columns.Add("Column2", typeof(string));
06    for (int id = 1; id <= 20; id++)
07        dataTable.Rows.Add(id, string.Format("A{0}", id), string.Format("B{0}", id));
08 
09    dataGridView.DataSource = dataTable;
10}

响应鼠标的按下抬起事件:

01private void dataGridView_MouseDown(object sender, MouseEventArgs e)
02{
03    // 通过鼠标按下的位置获<script type="text/javascript"><!--mce:0--></script><script type="text/javascript"><!--mce:1--></script><script type="text/javascript"><!--mce:2--></script><script type="text/javascript"><!--mce:3--></script>取所在行的信息
04    var hitTest = dataGridView.HitTest(e.X, e.Y);
05    if (hitTest.Type != DataGridViewHitTestType.Cell)
06        return;
07 
08    // 记下拖动源数据行的索引及已鼠标按下坐标为中心的不会开始拖动的范围
09    indexOfItemUnderMouseToDrag = hitTest.RowIndex;
10    if (indexOfItemUnderMouseToDrag > -1)
11    {
12        Size dragSize = SystemInformation.DragSize;
13        dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
14    }
15    else
16        dragBoxFromMouseDown = Rectangle.Empty;
17 
18}
19 
20private void dataGridView_MouseUp(object sender, MouseEventArgs e)
21{
22    // 释放鼠标按键时清空变量为默认值
23    dragBoxFromMouseDown = Rectangle.Empty;
24}


鼠标在按下状态移动时开始拖放过程:

01private void dataGridView_MouseMove(object sender, MouseEventArgs e)
02{
03    // 不是鼠标左键按下时移动
04    if ((e.Button & MouseButtons.Left) != MouseButtons.Left)
05        return;
06    // 如果鼠标在不启用拖动的范围内
07    if (dragBoxFromMouseDown == Rectangle.Empty || dragBoxFromMouseDown.Contains(e.X, e.Y))
08        return;
09    // 如果源数据行索引值不正确
10    if (indexOfItemUnderMouseToDrag < 0)
11        return;
12 
13    // 开始拖动,第一个参数表示要拖动的数据,可以自定义,一般是源数据行
14    var row = dataGridView.Rows[indexOfItemUnderMouseToDrag];
15    DragDropEffects dropEffect = dataGridView.DoDragDrop(row, DragDropEffects.All);
16 
17    //拖动过程结束后清除拖动位置行的红线效果
18    OnRowDragOver(-1);
19}


鼠标拖动过程中移动过数据行时执行重绘:

01private void dataGridView_DragOver(object sender, DragEventArgs e)
02{
03    // 把屏幕坐标转换成控件坐标
04    Point p = dataGridView.PointToClient(new Point(e.X, e.Y));
05 
06    // 通过鼠标按下的位置获取所在行的信息
07    // 如果不是在数据行或者在源数据行上则不能作为拖放的目标
08    var hitTest = dataGridView.HitTest(p.X, p.Y);
09    if (hitTest.Type != DataGridViewHitTestType.Cell || hitTest.RowIndex == indexOfItemUnderMouseToDrag)
10    {
11        e.Effect = DragDropEffects.None;
12        OnRowDragOver(-1);
13        return;
14    }
15 
16    // 设置为作为拖放移动的目标
17    e.Effect = DragDropEffects.Move;
18    // 通知目标行重绘
19    OnRowDragOver(hitTest.RowIndex);
20}

 

鼠标拖放至目标行释放时:

01private void dataGridView_DragDrop(object sender, DragEventArgs e)
02{
03    // 把屏幕坐标转换成控件坐标
04    Point p = dataGridView.PointToClient(new Point(e.X, e.Y));
05 
06    // 如果当前位置不是数据行
07    // 或者刚好是源数据行的下一行(本示例中假定拖放操作为拖放至目标行的上方)
08    // 则不进行任何操作
09    var hitTest = dataGridView.HitTest(p.X, p.Y);
10    if (hitTest.Type != DataGridViewHitTestType.Cell || hitTest.RowIndex == indexOfItemUnderMouseToDrag + 1)
11        return;
12 
13    indexOfItemUnderMouseToDrop = hitTest.RowIndex;
14 
15    // * 执行拖放操作(执行的逻辑按实际需要)
16 
17    var tempRow = dataTable.NewRow();
18    tempRow .ItemArray = dataTable.Rows[indexOfItemUnderMouseToDrag].ItemArray;
19    dataTable.Rows.RemoveAt(indexOfItemUnderMouseToDrag);
20 
21    if (indexOfItemUnderMouseToDrag < indexOfItemUnderMouseToDrop)
22        indexOfItemUnderMouseToDrop--;
23 
24    dataTable.Rows.InsertAt(tempRow, indexOfItemUnderMouseToDrop);
25}


如果鼠标正拖放至行上方时绘制一条红线:

1private void dataGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
2{
3    // 如果当前行是鼠标拖放过程的所在行
4    if (e.RowIndex == indexOfItemUnderMouseOver)
5        e.Graphics.FillRectangle(Brushes.Red, e.RowBounds.X, e.RowBounds.Y, e.RowBounds.Width, 2);
6}

用到的方法,强制行进行重绘:

01private void OnRowDragOver(int rowIndex)
02{
03    // 如果和上次导致重绘的行是同一行则无需重绘
04    if (indexOfItemUnderMouseOver == rowIndex)
05        return;
06 
07    int old = indexOfItemUnderMouseOver;
08    indexOfItemUnderMouseOver = rowIndex;
09 
10    // 去掉原有行的红线
11    if (old > -1)
12        dataGridView.InvalidateRow(old);
13 
14    // 绘制新行的红线
15    if (rowIndex > -1)
16        dataGridView.InvalidateRow(rowIndex);
17}


这样就是可以实现拖放效果了,拖放后的逻辑操作你可以自定义
[点这里下载完整的示例代码]

 

原文地址:http://www.cnblogs.com/jeffrey84/archive/2010/01/14/1647265.html

转载于:https://www.cnblogs.com/kafony/archive/2010/10/05/1843043.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值