您的位置:首页 > 其它

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

2010-10-05 10:46 525 查看
效果预览:




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

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

view sourceprint?

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

view sourceprint?

01
private
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
}
响应鼠标的按下和抬起事件:

view sourceprint?

01
private
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
20
private
void
dataGridView_MouseUp(
object
sender,MouseEventArgs e)
21
{
22
// 释放鼠标按键时清空变量为默认值
23
dragBoxFromMouseDown =Rectangle.Empty;
24
}
鼠标在按下状态移动时开始拖放过程:

view sourceprint?

01
private
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
}
鼠标拖动过程中移动过数据行时执行重绘:

view sourceprint?

01
private
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
}
鼠标拖放至目标行释放时:

view sourceprint?

01
private
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
}
如果鼠标正拖放至行上方时绘制一条红线:

view sourceprint?

1
private
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
}
用到的方法,强制行进行重绘:

view sourceprint?

01
private
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐