Articles in this section
Category / Section

How to Drag and Drop a Row from one Detailsview to another Detailsview in the SfDataGrid?

10 mins read

In the SfDataGrid, it is not possible to perform row drag and drop operation within a grid and from one SfDataGrid to another, by default.  You can achieve this by deriving new class from the GridSelectionController class in the SfDataGrid. Refer to the links RowDragandDropwithinGrid, RowDragandDrop-OneSfDataGridtoanother for more information.

Likewise, you can perform row drag and drop operations from one Detailsview to another Detailsview by deriving new class from the GridSelectionController and overriding its virtual method, HandlePointerOperations().

To handle Drag and Drop of data, you need to wire the following VisualContainer’s events in the derived SelectionController class:

  • PreviewMouseMove
  • PreviewDrop

You need to instantiate the instance of the new class, GridSelectionControllerExt that is derived from the GridSelectionController for the DetailsView DataGrid’s SelectionController property to achieve the Drag and Drop between two DetailsViewGrid as shown in the following code example.

 

C#

this.grid.DetailsViewExpanded += grid_DetailsViewExpanded;
void grid_DetailsViewExpanded(object sender, GridDetailsViewExpandedEventArgs e)
 {   
           //Gets the Row index from the record.
            var rowIndex = this.grid.ResolveToRowIndex(e.Record);
           //Gets the Record index from the rowindex.
            var recordIndex = this.grid.ResolveToRecordIndex(rowIndex);
          //Gets the DetailsViewGrid.
            var detailsViewGrid = this.grid.GetDetailsViewGrid(recordIndex, this.grid.DetailsViewDefinition[0].RelationalColumn);
            if (detailsViewGrid != null && !(detailsViewGrid.SelectionController is GridSelectionControllerExt))
                //SelectionController for the DetailsViewDataGrid.
                detailsViewGrid.SelectionController = new GridSelectionControllerExt(detailsViewGrid, this.grid);
  }

 

The following code example shows how to derive a new class from the GridSelectionController.

 

C#

public class GridSelectionControllerExt:GridSelectionController
 {
       VisualContainer Container;
       SfDataGrid parentGrid = null;
        public GridSelectionControllerExt(SfDataGrid datagrid, SfDataGrid parent)
            : base(datagrid)
        {
            parentGrid = parent;
             //Loaded event of the DetailsViewGrid is wired here.
            datagrid.Loaded += datagrid_Loaded;
             //Unloaded event of the DetailsViewGrid is wired here.
            datagrid.Unloaded += datagrid_Unloaded;
        }
}

The earlier mentioned VisualContainer event is wired and unwired in the Loaded and Unloaded events of the SfDataGrid as shown in the following code example.

C#

void datagrid_Loaded(object sender, RoutedEventArgs e)
{
    //Gets the VisualContainer with the GetVisualContainer() helper method.
    Container = DataGrid.GetVisualContainer();
    //Fires when the row data is dropped on the specified position.
    Container.PreviewDrop += Container_PreviewDrop;
    //Fires when the mouse operation is performed.  
    Container.PreviewMouseMove += Container_PreviewMouseMove;
}
void datagrid_Unloaded(object sender, RoutedEventArgs e)
 {
    //Unwires the datagrid loaded event.
      DataGrid.Loaded -= datagrid_Loaded;
    //Unwires the previewMouseMove event.
      Container.PreviewMouseMove -= Container_PreviewMouseMove;
    //Unwires the previewDrop event.
      Container.PreviewDrop -= Container_PreviewDrop;
    //Unwires the Unloaded event.
      DataGrid.Unloaded -= datagrid_Unloaded;
  }

 

HandlePointerOperations

In the HandlePointerOperations() virtual method, you can set IsPointerPressed to true when the mouse pointer is pressed on the row of any of the two Detailsview DataGrid and you can also set IsPointerPressed to false when the mouse pointer is released.

The following code example illustrates how to override the HandlePointerOperations() virtual method in the GridSelectionController class.

 

C#

      //Initially IsPointerPressed is false. 
       public bool IsPointerPressed = false;
       public override void HandlePointerOperations(GridPointerEventArgs args, RowColumnIndex rowColumnIndex)
       {
       //Sets IsPointerPressed to false when mouse pointer is Released.
           if(args.Operation == PointerOperation.Released)
           {
               IsPointerPressed = false;
           }
       //Sets IsPointerPressed to true when mouse pointer is Pressed.
          if(args.Operation == PointerOperation.Pressed)
           {
               IsPointerPressed = true;
           }
           base.HandlePointerOperations(args, rowColumnIndex);
       }

 

Row Dragging

You can drag the row data from one DetailsviewGrid to another DetailsviewGrid or vice versa in the PreviewMouseMove event of the VisualContainer. You can get the corresponding row and column index based on the mouse pointer position by using the PointToCellRowColumnIndex () method in the VisualContainer.

You need to resolve the record index by the ResolveToRecordIndex() helper method in the SfDataGrid to retrieve the exact row data on view under mouse position. Now, drag the record with the specified DragDropEffects by using the WPF DragAndDrop as illustrated in the following code example.

C#

void Container_PreviewMouseMove(object sender, MouseEventArgs e)
 {
           var rowColumnIndex = Container.PointToCellRowColumnIndex(e.GetPosition(Container));
     // IsPointerPressed is true from the ProcessPointerPressed method when a row is dragged.
           if (!rowColumnIndex.IsEmpty && IsPointerPressed)
           {
               // Gets the RecordIndex by using the RowIndex.
               var index = DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);
               if (index != -1)
               {
// Gets the RecordIndex by using the RowIndex.
                   var recordIndex = DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);
//Gets the Record Data as RecordEntry by using the RecordIndex. 
                   var recordEntry = DataGrid.View.Records[recordIndex];
                   var data = new DataObject();
//Stores the specified DataGrid to this data along with the specified format "DataGrid."
                   data.SetData("DataGrid", DataGrid);
//Stores the specified recordEntry to this data along with the specified format "RecordEntry."
                   data.SetData("RecordEntry", recordEntry);
//Initiates the drag and drop operation for the specified source and data with permitted drag and drop effects.
                   DragDrop.DoDragDrop(DataGrid, data, DragDropEffects.Copy | DragDropEffects.Move);
               }
           }
  }

 

Dropping

You can perform the Drop operation by using the PreviewDrop event of the VisualContainer. The PreviewDrop event is fired when the row data is dropped into a particular position of the SfDataGrid. You need to check whether the dragged record and the DataGrid is matched with specified format and the dragged record is inserted into a particular position of the DetailsviewGrid as shown in the following code example.

C#

private void Container_PreviewDrop(object sender, DragEventArgs e)
 {
      //Checks whether the datagrid/recordentry is available on the format.
           if (!e.Data.GetDataPresent("DataGrid") || !e.Data.GetDataPresent("RecordEntry"))
               return;
          //Gets the current data grid whose row is to be dragged.
           var dragginggrid = e.Data.GetData("DataGrid") as SfDataGrid;
       //Gets the record entry from the row of the grid to be dragged.
           var recordentry = e.Data.GetData("RecordEntry") as RecordEntry;
 
            //Checks whether the dragged grid and the record is not equal to null.
           if (dragginggrid == null || recordentry == null)
               return;
       //After dropping the row the IsPointerPressed state should be false.
           (dragginggrid.SelectionController as GridSelectionControllerExt).IsPointerPressed = false;
           // Gets the current  RowColumnIndex based on the VisualContainer position.
           var rowColumnIndex = Container.PointToCellRowColumnIndex(e.GetPosition(Container));
           var draggingGrid= ((parentGrid.GetGridDetailsViewRecord(dragginggrid as DetailsViewDataGrid) as RecordEntry).Data as Employee).SalaryInfo;
           var dropGrid= ((parentGrid.GetGridDetailsViewRecord(DataGrid as DetailsViewDataGrid)as RecordEntry).Data as Employee).SalaryInfo;
           if (!rowColumnIndex.IsEmpty && vmFrom != null && vmTo != null)
           {
               // Gets the RecordIndex by using the RowIndex.
               var index = DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);
                if (index != -1)
                {
                    var removeItem = recordentry.Data as SalaryDetails;
                    // Remove the Selected Row Data from Source
                    draggingGrid.Remove(recordentry.Data as SalaryDetails);
                  
                    // Insert the removed Selected Row Data to Source based on RecordIndex
                    dropGrid.Insert(index, removeItem);
                }
                else
                {
                    draggingGrid.Remove(recordentry.Data as SalaryDetails);
                    dropGrid.Add(recordentry.Data as SalaryDetails);
                }         
  }
}

 

You can refer to the following link for Drag-and-Drop row from one DetailsviewGrid to another DetailsviewGrid in the WPF platform.

Sample:

WPF

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please sign in to leave a comment
Access denied
Access denied