Category / Section
How to remove and insert rows from one virtual grid to other through drag and drop in WinForms GridControl?
4 mins read
Drag and drop
You can insert and remove rows when the external data sources for the two virtual grids support insertion/removal of rows. This implements the deletion of rows from the source grid and inserts them into the target grid along with special drawing queues. Since these are virtual grids where the grid does not manage the data, the sample uses a derived grid and interacts with the virtual control methods like OnDragEnter, OnDragDrop, etc., to implement the requested behavior with custom visual cues being drawn as you drag.
C#
public class DnDGridControl : GridControl { public VirtDataSource virtDataSource = null; private Point mouseDownPoint = Point.Empty; private bool mouseDownInDrag = false; public DnDGridControl() : base() { this.AllowDrop = true; this.DataObjectConsumerOptions = Syncfusion.Windows.Forms.Grid.GridDataObjectConsumerOptions.None; this.ControllerOptions = ((((Syncfusion.Windows.Forms.Grid.GridControllerOptions.ClickCells | Syncfusion.Windows.Forms.Grid.GridControllerOptions.DragSelectRowOrColumn) | Syncfusion.Windows.Forms.Grid.GridControllerOptions.SelectCells) | Syncfusion.Windows.Forms.Grid.GridControllerOptions.ExcelLikeSelection) | Syncfusion.Windows.Forms.Grid.GridControllerOptions.ResizeCells); } #region controlling the cursor protected virtual void OnQueryShowTheDragCursor(QueryShowTheDragCursorEventArgs e) { if(QueryShowTheDragCursor != null) QueryShowTheDragCursor(this, e); } protected override void OnSetCursor(ref System.Windows.Forms.Message m) { if(Control.MouseButtons != MouseButtons.Left && QueryShowDndCursor()) { Cursor.Current = DnDGridControl.CanStartDragCursor; } else base.OnSetCursor(ref m); } protected override void OnDragDrop(System.Windows.Forms.DragEventArgs e) { CustomDragEventArgs ce = new CustomDragEventArgs(e); this.OnDropCustomData(ce); if(ce.Handled) { e.Effect = ce.Effect; return; } if(e.Data.GetDataPresent("SelectedRowObjects")) { e.Effect = DragDropEffects.Move; ArrayList data = (ArrayList)e.Data.GetData("SelectedRowObjects"); int row, col; Point pt1 = this.PointToClient(new Point(e.X, e.Y)); this.PointToRowCol(pt1, out row, out col); this.dropRowInThisGrid = row; this.BeginUpdate(); for(int i = data.Count - 1; i >= 0; --i) { this.virtDataSource.Insert(row - 1, data[i]); } this.EndUpdate(); this.Refresh(); return; } base.OnDragDrop(e); } protected override void OnDragEnter(System.Windows.Forms.DragEventArgs e) { int row, col; if(e.Data.GetDataPresent("Text")) { string s = (string)e.Data.GetData("Text"); string[] lines = s.Split('\n'); nDndRowExt = lines.GetLength(0); nDndColExt = nDndRowExt > 0 ? lines[0].Split('\t').GetLength(0) : 1; if(nDndRowExt > 1) nDndRowExt--; e.Effect = DragDropEffects.Move; Point pt1 = this.PointToClient(new Point(e.X, e.Y)); this.PointToRowCol(pt1, out row, out col); if(row != this.lastMarkedRow) this.UpdateTheRectangle(this.RangeInfoToRectangle(GridRangeInfo.Cells(row, this.LeftColIndex, row, this.ViewLayout.LastVisibleCol))); } } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { mouseDownPoint = new Point(e.X, e.Y); this.PointToRowCol(mouseDownPoint, out this.lastMarkedRow, out this.lastMarkedCol, -1); mouseDownInDrag = QueryShowDndCursor(); if(mouseDownInDrag) { // Drags with text data. string data = CopyText(); DataObject dataObj = new DataObject(data); CustomDataEventArgs cde = new CustomDataEventArgs(dataObj); OnSetCustomData(cde); //gets the selected row indexes GridRangeInfoList rangeList = this.Selections.GetSelectedRows(false, false); ArrayList a = new ArrayList(); ArrayList dataRows = new ArrayList(); foreach(GridRangeInfo range in rangeList) { for(int i = range.Top; i <= range.Bottom; ++i) { a.Add(i-1); //-1 because zero based index in data dataRows.Add(this.virtDataSource[i-1]); } } a.Sort(); //Sorts from top to bottom for ease of deleting. ((DataObject)cde.Data).SetData("SelectedRowObjects", dataRows); this.dropRowInThisGrid = -1; DragDropEffects dde = this.DoDragDrop(cde.Data, DragDropEffects.Move); if(dde == DragDropEffects.Move) { this.BeginUpdate(); for(int i = a.Count - 1; i >= 0; --i) { int offSet = (dropRowInThisGrid == -1 || dropRowInThisGrid > (int)a[i]) ? 0 : a.Count - i; this.virtDataSource.RemoveAt(offSet + (int)a[i]); } this.EndUpdate(); this.Refresh(); } ResetDrag(); return; } base.OnMouseDown(e); }
VB
Public Class DnDGridControl Inherits GridControl Public virtDataSource As VirtDataSource = Nothing Private mouseDownPoint As Point = Point.Empty Private mouseDownInDrag As Boolean = False Public Sub New() MyBase.New() Me.AllowDrop = True Me.DataObjectConsumerOptions = Syncfusion.Windows.Forms.Grid.GridDataObjectConsumerOptions.None Me.ControllerOptions = ((((Syncfusion.Windows.Forms.Grid.GridControllerOptions.ClickCells Or Syncfusion.Windows.Forms.Grid.GridControllerOptions.DragSelectRowOrColumn) Or Syncfusion.Windows.Forms.Grid.GridControllerOptions.SelectCells) Or Syncfusion.Windows.Forms.Grid.GridControllerOptions.ExcelLikeSelection) Or Syncfusion.Windows.Forms.Grid.GridControllerOptions.ResizeCells) End Sub #Region "controlling the cursor" Protected Overridable Sub OnQueryShowTheDragCursor(ByVal e As QueryShowTheDragCursorEventArgs) RaiseEvent QueryShowTheDragCursor(Me, e) End Sub Protected Overrides Sub OnSetCursor(ByRef m As System.Windows.Forms.Message) If Control.MouseButtons <> MouseButtons.Left AndAlso QueryShowDndCursor() Then Cursor.Current = DnDGridControl.CanStartDragCursor Else MyBase.OnSetCursor(m) End If End Sub Protected Overrides Sub OnDragDrop(ByVal e As System.Windows.Forms.DragEventArgs) Dim ce As New CustomDragEventArgs(e) Me.OnDropCustomData(ce) If ce.Handled Then e.Effect = ce.Effect Return End If If e.Data.GetDataPresent("SelectedRowObjects") Then e.Effect = DragDropEffects.Move Dim data As ArrayList = CType(e.Data.GetData("SelectedRowObjects"), ArrayList) Dim row, col As Integer Dim pt1 As Point = Me.PointToClient(New Point(e.X, e.Y)) Me.PointToRowCol(pt1, row, col) Me.dropRowInThisGrid = row Me.BeginUpdate() For i As Integer = data.Count - 1 To 0 Step -1 Me.virtDataSource.Insert(row - 1, data(i)) Next i Me.EndUpdate() Me.Refresh() Return End If MyBase.OnDragDrop(e) End Sub Protected Overrides Sub OnDragEnter(ByVal e As System.Windows.Forms.DragEventArgs) Dim row, col As Integer If e.Data.GetDataPresent("Text") Then Dim s As String = CStr(e.Data.GetData("Text")) Dim lines() As String = s.Split(ControlChars.Lf) nDndRowExt = lines.GetLength(0) nDndColExt = If(nDndRowExt > 0, lines(0).Split(ControlChars.Tab).GetLength(0), 1) If nDndRowExt > 1 Then nDndRowExt -= 1 End If e.Effect = DragDropEffects.Move Dim pt1 As Point = Me.PointToClient(New Point(e.X, e.Y)) Me.PointToRowCol(pt1, row, col) If row <> Me.lastMarkedRow Then Me.UpdateTheRectangle(Me.RangeInfoToRectangle(GridRangeInfo.Cells(row, Me.LeftColIndex, row, Me.ViewLayout.LastVisibleCol))) End If End If End Sub Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs) mouseDownPoint = New Point(e.X, e.Y) Me.PointToRowCol(mouseDownPoint, Me.lastMarkedRow, Me.lastMarkedCol, -1) mouseDownInDrag = QueryShowDndCursor() If mouseDownInDrag Then 'Drags with text data Dim data As String = CopyText() Dim dataObj As New DataObject(data) Dim cde As New CustomDataEventArgs(dataObj) OnSetCustomData(cde) 'gets the selected row indexes Dim rangeList As GridRangeInfoList = Me.Selections.GetSelectedRows(False, False) Dim a As New ArrayList() Dim dataRows As New ArrayList() For Each range As GridRangeInfo In rangeList For i As Integer = range.Top To range.Bottom a.Add(i-1) '-1 because zero based index in data dataRows.Add(Me.virtDataSource(i-1)) Next i Next range a.Sort() 'Sorts from top to bottom for ease of deleting. CType(cde.Data, DataObject).SetData("SelectedRowObjects", dataRows) Me.dropRowInThisGrid = -1 Dim dde As DragDropEffects = Me.DoDragDrop(cde.Data, DragDropEffects.Move) If dde = DragDropEffects.Move Then Me.BeginUpdate() For i As Integer = a.Count - 1 To 0 Step -1 Dim offSet As Integer = If((dropRowInThisGrid = -1 OrElse dropRowInThisGrid > CInt(Fix(a(i)))), 0, a.Count - i) Me.virtDataSource.RemoveAt(offSet + CInt(Fix(a(i)))) Next i Me.EndUpdate() Me.Refresh() End If ResetDrag() Return End If MyBase.OnMouseDown(e) End Sub
Samples:
C#: Adding_and_removing_rows_in_virtualgrid
VB: Adding_and_removing_rows_in_virtualgrid
Reference link: https://help.syncfusion.com/windowsforms/grid-control/drag-and-drop