DataGridView multirow select clearing left click drag

I am trying to implement Drag and Drop for multiple rows in a standard DataGridView.

I select 3 lines while holding down the control key and left mouse button. Then I turn off the control key and select the rows to drag and drop. Therefore, using the left mouse button, I press and hold the button on one of the lines, so I can start the drag and drop movement.

However, as soon as I click on one of the lines, this line is selected and the remaining 2 lines are selected, so I no longer move 3 lines.

How can I get around this problem? I would only expect the line to be highlighted again if I released the left mouse button (without the ctrl key). This is how Windows Explorer works.

I am using C # 4.0 in Visual Studio 2010.

+4
source share
2 answers

I ran into this exact problem in the project - how to allow the user to use standard methods to select a group of rows in a datagridview, and then drag the selection to another datagrid view and delete it. I was able to build an idea from http://www.codeproject.com/Tips/338594/Drag-drop-multiple-selected-rows-of-datagridview-w , which simply subclasses the DataGridView as a “draggable” DataGridView, capturing mouse actions when the user presses a button on an already selected line, providing standard behavior for all other cases:

public partial class DraggableDataGridView : System.Windows.Forms.DataGridView { private Rectangle dragBoxFromMouseDown; protected override void OnMouseDown(MouseEventArgs e) { // Trap the case where the user pressed the left mouse button on an already-selected row // without <shift> or <control> if ((e.Button & MouseButtons.Left) == MouseButtons.Left && Control.ModifierKeys == Keys.None && this.SelectedRows.Count > 0 && HitTest(eX, eY).RowIndex >= 0 && this.SelectedRows.Contains(this.Rows[HitTest(eX, eY).RowIndex]) ) { // User pressed the mouse button over an already-selected row without <shift> or <control> so we should // consider drag and drop. Record a rectangle around that mouse location to possibly trigger drag // operation Debug.WriteLine("MouseDown inside selection"); Size dragSize = SystemInformation.DragSize; dragBoxFromMouseDown = new Rectangle(new Point(eX - (dragSize.Width / 2), eY - (dragSize.Height / 2)), dragSize); } else { // In other cases use the default behavior for datagridview Debug.WriteLine("MouseDown outside selection"); dragBoxFromMouseDown = Rectangle.Empty; base.OnMouseDown(e); } } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); } protected override void OnMouseMove(MouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { // If the mouse moves outside the drag limit rectangle, start the drag. if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.Location)) { // Proceed with the drag and drop, passing in the selected rows DragDropEffects dropEffect = this.DoDragDrop(this.SelectedRows, DragDropEffects.Move); } } base.OnMouseMove(e); } public DraggableDataGridView() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); } } 

Having this code, and then replacing this custom component for all my DataGridViews in forms, allowed me to use them as a standard drag and drop source and “connect” them to the standard drop functions for other components in the usual way.

+1
source

I don't have a much simpler solution, but this should work. The whole idea is to change the selected BackColor lines to SelectionBackColor and the selected ForeColor lines to SelectionForeColor . They look as if they are selected. I suppose DataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect it is easy to get SelectedRows , and not select rows by clicking on row headers. I also assume that Form.KeyPreview = true

Here is my code:

 //This is to copy the SelectedRows every time user releases the Control key DataGridViewRow[] selectedRows; private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e){ if(selectedRows == null) return; if(!selectedRows.Contains(dataGridView.Rows[e.RowIndex])){ //Restore the BackColor and ForeColor of the selected rows foreach(DataGridViewRow row in selectedRows){ row.DefaultCellStyle.BackColor = dataGridView.DefaultCellStyle.BackColor; row.DefaultCellStyle.ForeColor = dataGridView.DefaultCellStyle.ForeColor; } } } private void form_KeyUp(object sender, KeyEventArgs e){ if(e.KeyCode == Keys.ControlKey){ selectedRows = new DataGridViewRow[dataGridView.SelectedRows.Count]; dataGridView.SelectedRows.CopyTo(selectedRows,0); foreach(DataGridViewRow row in selectedRows){ row.DefaultCellStyle.BackColor = dataGridView.DefaultCellStyle.SelectionBackColor; row.DefaultCellStyle.ForeColor = dataGridView.DefaultCellStyle.SelectionForeColor; } } } 

I hope you understand the whole idea, to set it up and encode it yourself, for example, restore BackColor and ForeColor if the lost focus is dataGridView ...

I hope this helps, and someone can give a better solution!

0
source

Source: https://habr.com/ru/post/1484169/


All Articles