如何在单元格上按住鼠标时在DataGridView中维护选定的行?

我试图在DataGridView中实现行移动。 我希望能够选择多行并单击任何选定行的单元格以开始拖动操作。 问题是当我将鼠标放在单元格上时,行将被取消选择。 我怎样才能防止这种情况发生?

通过快速谷歌搜索, 这似乎是自定义拖放行的解决方案。 注意我刚刚从链接页面中删除了以下代码,我无法保证其有效性。

private Rectangle dragBoxFromMouseDown; private int rowIndexFromMouseDown; private int rowIndexOfItemUnderMouseToDrop; private void dataGridView1_MouseMove(object sender, MouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { // If the mouse moves outside the rectangle, start the drag. if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(eX, eY)) { // Proceed with the drag and drop, passing in the list item. DragDropEffects dropEffect = dataGridView1.DoDragDrop(dataGridView1.Rows[rowIndexFromMouseDown], DragDropEffects.Move); } } } private void dataGridView1_MouseDown(object sender, MouseEventArgs e) { // Get the index of the item the mouse is below. rowIndexFromMouseDown = dataGridView1.HitTest(eX, eY).RowIndex; if (rowIndexFromMouseDown != -1) { // Remember the point where the mouse down occurred. // The DragSize indicates the size that the mouse can move // before a drag event should be started. Size dragSize = SystemInformation.DragSize; // Create a rectangle using the DragSize, with the mouse position being // at the center of the rectangle. dragBoxFromMouseDown = new Rectangle(new Point(eX - (dragSize.Width / 2), eY - (dragSize.Height / 2)), dragSize); } else { // Reset the rectangle if the mouse is not over an item in the ListBox. dragBoxFromMouseDown = Rectangle.Empty; } } private void dataGridView1_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Move; } private void dataGridView1_DragDrop(object sender, DragEventArgs e) { // The mouse locations are relative to the screen, so they must be // converted to client coordinates. Point clientPoint = dataGridView1.PointToClient(new Point(eX, eY)); // Get the row index of the item the mouse is below. rowIndexOfItemUnderMouseToDrop = dataGridView1.HitTest(clientPoint.X, clientPoint.Y).RowIndex; // If the drag operation was a move then remove and insert the row. if (e.Effect== DragDropEffects.Move) { DataGridViewRow rowToMove = e.Data.GetData(typeof(DataGridViewRow)) as DataGridViewRow; dataGridView1.Rows.RemoveAt(rowIndexFromMouseDown); dataGridView1.Rows.Insert(rowIndexOfItemUnderMouseToDrop, rowToMove); } } 

对datagridview进行子类化可帮助您以条件方式执行此操作:

 class SimpleDataGridView : DataGridView { public Action BeforeCellMouseDown; public Action AfterCellMouseDown; protected override void OnCellMouseDown(DataGridViewCellMouseEventArgs e) { if(BeforeCellMouseDown != null) BeforeCellMouseDown(e); base.OnCellMouseDown(e); if(AfterCellMouseDown != null) AfterCellMouseDown(e); } } 

然后,您可以在构造函数中以这种方式使用它:

 IEnumerable sel = null; dataGridView1.BeforeCellMouseDown = e => { if (yourCondition) // Save the selection sel = dataGridView1.SelectedRows.OfType(); else sel = null; }; dataGridView1.AfterCellMouseDown = e => { if(sel != null) { // Restore the selection foreach(var row in sel) row.Selected = true; } }; 

我个人不确定如何更改您正在讨论的问题的默认行为,但我知道默认情况下右键单击不会对DataGridView执行任何操作。 话虽如此,解决方法可能是实现我以前做过的事情:自定义ContextMenuStrip允许用户通过选择行来复制/粘贴行,右键单击以打开上下文菜单,复制行,然后右键 – 单击行标题以打开上下文菜单并粘贴。 CellClick和RowHeaderMouseClick事件应该使这更容易。