C# DataGridView Drag and Drop

Ein DateGridView mit Drag and Drop der gesamten Zeile.
– Multiselect möglich (verschiebt alle markierten Zeilen)
– Behällt die selektieren Zeilen nach dem ablegen
– Zeigt einen visuellen Strich am Einfügepunkt ober oder unterhalb der Zeile
– Scrollt automatisch hoch/runter


 //works with multiselect rows
 //shows divider
 //todo after dragover click on multiselect rows deselect it
 private static int rowIndexFrom = -1;
 private static int rowIndexTo = -1;
 private static int[] dataGridViewSelectedRows = null;
 private void dataGridView1_Paint(object sender, PaintEventArgs e)
 {
     if (rowIndexTo == -1) return;
     var dataGridView = sender as DataGridView;
     var rect = dataGridView1.GetRowDisplayRectangle(rowIndexTo, false);
     int posY = (rowIndexTo > rowIndexFrom && !dataGridView.Rows[rowIndexTo].IsNewRow)
                ? rect.Bottom : rect.Top;
     using (var pen = new Pen(Color.FromArgb(150, 33, 186, 71), 7))
         e.Graphics.DrawLine(pen, new Point(rect.Left, posY - 1), new Point(rect.Right, posY - 1));
     
 }
 private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
 {
 }
 private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
 {
     if ((e.Button & MouseButtons.Left) != MouseButtons.Left) { rowIndexTo = -1; return; }
     var dataGridView = sender as DataGridView;
     if (!dataGridView1.AllowDrop || dataGridView.ReadOnly || dataGridView.SelectedRows.Count == 0) { rowIndexTo = -1; return; }
     var hitTestInfo = dataGridView.HitTest(e.X, e.Y);
     if (hitTestInfo.ColumnIndex == -1)
     {
         
     }
     foreach (DataGridViewRow row in dataGridView.SelectedRows)
         if (row.IsNewRow) row.Selected = false;
     dataGridViewSelectedRows = dataGridView.SelectedRows.Cast().Select(row => row.Index).ToArray();
     if (dataGridView1.SelectedRows.Count == 0) { rowIndexFrom = -1; return; }
     rowIndexFrom = hitTestInfo.RowIndex;
     if (dataGridViewSelectedRows.Contains(rowIndexFrom))
     {
         dataGridView.EndEdit();
         Task.Factory.StartNew(() =>
         {
             dataGridView.Invoke(new Action(() =>
             {
                 if (dataGridViewSelectedRows?.Length > 1)
                     foreach (int row in dataGridViewSelectedRows) dataGridView.Rows[row].Selected = true;
                 if (rowIndexFrom != -1 && dataGridView.Rows.Count >= dataGridViewSelectedRows?.Length)
                     dataGridView.DoDragDrop(0, DragDropEffects.Move);
             }));
         });
     }
 }
 private void dataGridView1_DragOver(object sender, DragEventArgs e)
 {
     if (rowIndexFrom == -1) return;
     var dataGridView = sender as DataGridView;
     if (!dataGridView.AllowDrop || dataGridView.ReadOnly || dataGridView.SelectedRows.Count <= 0) { rowIndexTo = -1; return; }
     e.Effect = DragDropEffects.Move;
     try
     {
        
         Point clientPointer = dataGridView.PointToClient(new Point(e.X, e.Y));
         rowIndexTo = dataGridView.HitTest(clientPointer.X, clientPointer.Y).RowIndex;
         if (dataGridView.Rows[rowIndexTo].IsNewRow) { rowIndexTo--; }
         
     }
     catch
     {
         rowIndexTo = -1;
     }
     if (dataGridViewSelectedRows?.Length > 1 && dataGridViewSelectedRows.Contains(rowIndexTo) && dataGridViewSelectedRows.Contains(rowIndexTo - 1))
     {
         rowIndexTo = -1;
     }
     #region Scrollen beim Verschieben von Zeilen
     Point clientPoint = dataGridView.PointToClient(new Point(e.X, e.Y));
     //Converts window position to user control position (otherwise you can use MousePosition.Y)
     int mousepos = PointToClient(Cursor.Position).Y;
     //If the mouse is hovering over the bottom 5% of the grid
     if (mousepos > (dataGridView1.Location.Y + (dataGridView1.Height * 0.95)))
     {
         mouseMoveDown = true;
         //If the first row displayed isn't the last row in the grid
         if (dataGridView1.FirstDisplayedScrollingRowIndex < dataGridView1.RowCount - 1)
         {
             //Increase the first row displayed index by 1 (scroll down 1 row)
             int firstDisplRow = dataGridView1.FirstDisplayedScrollingRowIndex;
             if (dataGridView1.Rows[firstDisplRow + 1].Displayed)
             {
                 Thread.Sleep(60);
                 dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.FirstDisplayedScrollingRowIndex + 1;
             }
         }
     }
     //If the mouse is hovering over the top 5% of the grid
     if (mousepos < (dataGridView1.Location.Y + (dataGridView1.Height * 0.55)))
     {
         mouseMoveDown = false;
         //If the first row displayed isn't the first row in the grid
         if (dataGridView1.FirstDisplayedScrollingRowIndex > 1)
         {
             int firstDisplRow = dataGridView1.FirstDisplayedScrollingRowIndex;
             Thread.Sleep(60);
             dataGridView1.FirstDisplayedScrollingRowIndex -= 1;
         }
     }
     #endregion
     dataGridView.Refresh();
 }
 private void dataGridView1_DragDrop(object sender, DragEventArgs e)
 {
     if (rowIndexTo == -1) return;
     var dataGridView = sender as DataGridView;
     if (!dataGridView.AllowDrop || dataGridView.ReadOnly || dataGridView.SelectedRows.Count <= 0) { rowIndexTo = -1; dataGridView.Refresh(); return; }
     if (rowIndexTo == rowIndexFrom && dataGridView.SelectedRows.Count == 1) { rowIndexTo = -1; dataGridView.Refresh(); return; }
     if (rowIndexTo == -1) { dataGridView.Refresh(); return; }
     if (e.Effect == DragDropEffects.Move)
     {
         dataGridView.Invoke(new Action(() =>
         {
             List rowsToMove = dataGridView.SelectedRows.Cast().OrderBy(row => row.Index).ToList();
             bool indexInbetweenRows = rowIndexTo > rowsToMove.Min(row => row.Index) && rowIndexTo < rowsToMove.Max(row => row.Index);
             if (indexInbetweenRows) rowIndexTo = rowsToMove.Min(row => row.Index);
             rowIndexTo = rowIndexFrom >= rowIndexTo ? rowIndexTo : rowIndexTo - (rowsToMove.Count - 1);
             foreach (DataGridViewRow row in rowsToMove) dataGridView.Rows.Remove(row);
             int insertIndex = rowIndexTo;
             rowsToMove.ForEach(row => dataGridView.Rows.Insert(insertIndex++, row));
             dataGridView.ClearSelection();
             dataGridView.CurrentCell = dataGridView.Rows[rowIndexTo].Cells[dataGridView.FirstDisplayedCell.ColumnIndex];
             rowsToMove.ForEach(row => row.Selected = true);
         }));
     }
     rowIndexTo = -1;
     dataGridView.Refresh();
 }
 private void dataGridView1_MouseLeave(object sender, EventArgs e)
 {
     rowIndexTo = -1; 
     dataGridView1.Refresh();
 }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert