A newer version of this page is available. Switch to the current version.

VerticalGrid as the Source of Drag and Drop

  • 11 minutes to read

This topic provides an example of using a vertical grid as a source for OLE drag and drop operations. It shows how to customize the grid so that end-users can drag data records to different controls. For a general OLE drag and drop overview, please refer to the OLE Drag and Drop Overview topic.

Dragging Records from the Vertical Grid. A Detailed Description

You can use the code listed in this section to allow end-users to drag data records to other controls or applications. The code will handle the vertical grid’s MouseMove event to initiate dragging. The following main tasks are performed by the event handler:

  • Determine the element located under the mouse cursor. If the element is not a value cell, dragging is not initialized. Otherwise, the cell owner’s record index is obtained.
  • Obtain the values for the record located underneath the mouse cursor. Row header captions and their corresponding cell values are written to a string variable.
  • Initiate dragging. This is performed by using the DoDragDrop method call, the previously constructed string is now passed to this method as dragged data. The method enables copy and move operations to be performed by the target control.
  • Determine the results of the drag and drop operation. If the data needs to be moved, then the record is deleted from the vertical grid control’s data source.

Let’s consider the implementation of each step in detail. After they are all described, the code will be listed in its entirety.

First of all it is necessary to determine when the drag and drop operation should start. For this purpose, the MouseDown and MouseMove events will be handled. The MouseDown event handler will store the click point to a variable. The MouseMove event handler determines the mouse cursor’s offset position relative to the point stored in the MouseDown handler. If the offset does not exceed 10 pixels either horizontally or vertically, no further processing will occur. Note that the vertical grid should be set to a read only state when the mouse button is pressed, otherwise the current cell’s editor will be activated. So, the MouseUp event handler must be used to make the grid editable again.


Point startDragPoint;
bool dragging = false;

private void vGridControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   startDragPoint = new Point(e.X, e.Y);
   dragging = true;
   vGrid.OptionsBehavior.Editable = false;
}

private void vGridControl1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   dragging = false;
   vGrid.OptionsBehavior.Editable = true;
}

private void vGridControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
   if (!dragging) return;
   int deltaX = e.X - startDragPoint.X;
   int deltaY = e.Y - startDragPoint.Y;
   if ((Math.Abs(deltaX) < 10) && (Math.Abs(deltaY) < 10)) return;
   // ...
}

To determine the element located underneath the mouse cursor, you will need to use the VGridControlBase.CalcHitInfo method. This method accepts a point as a parameter and returns an object containing information about what resides at the point passed to it. This object’s properties can be used to determine the element type which resides at the specified coordinates and determine the row, record, cell and band where the point is located. Please refer to the Obtain Hit Information topic for details on using this VGridControlBase.CalcHitInfo method and the object returned.

The sample code below is part of the MouseMove event handler which is used to determine the record located under the drag and drop starting point.


private void vGridControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   // ...
   VGridHitInfo hitInfo = vGrid.CalcHitInfo(startDragPoint);
   int recordIndex = hitInfo.RecordIndex;
   if (recordIndex == -1) return;
   // ...
}

The next step to perform is to construct a string to represent the dragged data. This string is constructed of row captions and their corresponding cell values separated by a carriage return. For multi-editor rows captions and values for each row item are separated from each other using the ‘|’ character. To construct such a string, it is necessary to visit each row within the control. This is performed by means of the Rows Iterator.

The code below shows how to construct the desired string. The operation class used to obtain cell values is declared. Then a portion of the MouseMove event handler is listed. It uses the rows iterator to execute the declared operation.


public class GetRecordValuesOperation : RowOperation {
   int recordIndex;
   VGridControl grid;
   string cellValues;
   public GetRecordValuesOperation(VGridControl grid, int recordIndex) : base() {
      this.recordIndex = recordIndex;
      this.grid = grid;
      this.cellValues = "";
   }
   public override void Execute(BaseRow row) {
      if (row is EditorRow)
         cellValues += row.Properties.Caption + ": " + grid.GetCellValue(row, recordIndex).ToString() + "\n";
      else if (row is MultiEditorRow) {
         MultiEditorRow meRow = row as MultiEditorRow;
         string meRowValues = "";
         foreach (MultiEditorRowProperties props in meRow.PropertiesCollection)
            meRowValues += props.Caption + ": " + grid.GetCellValue(props, recordIndex).ToString() + " | ";
         cellValues += meRowValues.Substring(0, meRowValues.Length - 3) + "\n";
      }
   }
   public string CellValues { get { return cellValues; } }
}

private void vGridControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   // ...
   GetRecordValuesOperation operation = new GetRecordValuesOperation(vGrid, recordIndex);
   vGrid.RowsIterator.DoOperation(operation);
   string dragData = operation.CellValues;
   // ...
}

Once the data to drag has been obtained, the drag and drop operation can start. This is performed using the following line of code:


private void vGridControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   // ...
   DragDropEffects effect = vGrid.DoDragDrop(dragData, DragDropEffects.Copy | DragDropEffects.Move);
   // ...
}

The DoDragDrop method called in the line of code above returns a value after the drag and drop operation completes. This value needs to be evaluated since it determines the type of action performed, either copying or moving data. If the data has been moved, the dragged record needs to be deleted. The code below shows how this can be performed. It assumes that a DataTable object is used as the vertical grid control’s data source.


private void vGridControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   // ...
   if (effect == DragDropEffects.Move) {
      (vGrid.DataSource as DataTable).Rows.RemoveAt(recordIndex);
      oleDbDataAdapter1.Update(vGrid.DataSource as DataTable);
   }
}

Please refer to the Adding and Deleting Records topic for details on how to delete records in the VGridControl control.

Dragging Records from the Vertical Grid. The Complete Code

Below is the entire code needed to drag records from the VGridControl control.


using DevExpress.XtraVerticalGrid;
using DevExpress.XtraVerticalGrid.Rows;
// ...
Point startDragPoint;
bool dragging = false;

private void vGridControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   startDragPoint = new Point(e.X, e.Y);
   dragging = true;
   vGrid.OptionsBehavior.Editable = false;
}

private void vGridControl1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   dragging = false;
   vGrid.OptionsBehavior.Editable = true;
}

private void vGridControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
   VGridControl vGrid = sender as VGridControl;
   if (!dragging) return;
   int deltaX = e.X - startDragPoint.X;
   int deltaY = e.Y - startDragPoint.Y;
   if ((Math.Abs(deltaX) < 10) && (Math.Abs(deltaY) < 10)) return;
   VGridHitInfo hitInfo = vGrid.CalcHitInfo(startDragPoint);
   int recordIndex = hitInfo.RecordIndex;
   if (recordIndex == -1) return;
   GetRecordValuesOperation operation = new GetRecordValuesOperation(vGrid, hitInfo.RecordIndex);
   vGrid.RowsIterator.DoOperation(operation);
   string dragData = operation.CellValues;
   DragDropEffects effect = vGrid.DoDragDrop(dragData, DragDropEffects.Copy | DragDropEffects.Move);      
   if (effect == DragDropEffects.Move) {
      (vGrid.DataSource as DataTable).Rows.RemoveAt(recordIndex);
      oleDbDataAdapter1.Update(vGrid.DataSource as DataTable);
   }
}

public class GetRecordValuesOperation : RowOperation {
   int recordIndex;
   VGridControl grid;
   string cellValues;
   public GetRecordValuesOperation(VGridControl grid, int recordIndex) : base() {
      this.recordIndex = recordIndex;
      this.grid = grid;
      this.cellValues = "";
   }
   public override void Execute(BaseRow row) {
      if (row is EditorRow)
         cellValues += row.Properties.Caption + ": " + grid.GetCellValue(row, recordIndex).ToString() + "\n";
      else if (row is MultiEditorRow) {
         MultiEditorRow meRow = row as MultiEditorRow;
         string meRowValues = "";
         foreach (MultiEditorRowProperties props in meRow.PropertiesCollection)
            meRowValues += props.Caption + ": " + grid.GetCellValue(props, recordIndex).ToString() + " | ";
         cellValues += meRowValues.Substring(0, meRowValues.Length - 3) + "\n";
      }
   }
   public string CellValues { get { return cellValues; } }
}

The image below shows an example of moving record values to a Microsoft Word document.

DragDrop - Source_New