Other DevExpress WinForms Cheat Sheets
Built-in drag-and-drop
The following DevExpress WinForms controls support inner drag-and-drop operations out of the box.
- TileView - Tile drag-and-drop (the AllowDrag option).
- Vertical Grid - Row drag-and-drop (the DragRowHeaders property).
- Tree List - Node drag-and-drop (the DragNodesMode) property) .
- Scheduler - Appointment drag-and-drop (SchedulerControl.OptionsCustomization.AllowAppointmentDrag).
Drag-and-Drop Behavior - Drag-and-drop within and between DevExpress controls
Drag-and-Drop Behavior (part of the BehaviorManager component) allows drag-and-drop operations between and within the following controls:
- Data Grid ( GridView, its descendants and TileView)
- TreeList
- ListBoxControl
The Drag-and-Drop Behavior has the following features:
- A drag operation is initiated automatically. You do not need to handle mouse events.
- The Behavior displays previews of dragged items.
- Events allow you to identify data items, customize preview images, cancel operations, etc.
- To allow a drag-and-drop between two controls (from one grid to another, from a grid to a tree list, etc.), create two Drag-and-Drop Behavior objects. Attach them to both controls.
- If the data structure of the source and target controls differs, handle drag events to convert data items.
- The Drag-and-Drop Behavior does not perform drag-and-drop operations if a control's Control.AllowDrop property is set to
true
. It is assumed that the standard .NET drag-and-drop engine will be used in this case.
The standard .NET drag-and-drop engine
If the techniques above do not suit your needs, consider using the standard drag-and-drop engine. It allows you to implement drag-and-drop operations between and within controls and applications of any complexity. See Performing a Drag-and-Drop Operation in Windows Forms for more information.
Note: To avoid conflicts, do not use the standard .NET drag-and-drop engine together with DevExpress controls' built-in drag-and-drop operations and Drag-and-Drop Behavior.
See also:
- DataGrid - Drag-and-Drop Grid Rows
- Drag-and-Drop Tree List Nodes
- Scheduler - Drag-and-Drop Operations
- Vertical Grid - Drag and Drop
Examples
Update underlying data sources
Built-in drag-and-drop operations and Drag-and-Drop Behavior of DevExpress controls do not update underlying data sources to reflect visual changes. Handle the event that fires when a data element is dropped onto a control to update the underlying data source.
Start drag-and-drop operations when a user clicks a cell with an inplace editor
A drag-and-drop operation in grid and treelist controls is initiated when a user clicks a row. The operation is canceled if a mouse press activates an in-place cell editor because the cell editor will handle all subsequent mouse events in this case. To prevent in-place editor activation during a drag-and-drop operation, set the EditorShowMode option to Click or MouseUp.
You may wish to refer to the following links for more information:
Reorder grid rows in the Grid View (tiles in the Tile View)
To enable users to reorder rows in Data Grid, do the following:
- Attach the Drag-and-Drop Behavior to the GridView or TileView.
- Handle the DragOver event to display the insert indicator and update the mouse pointer.
- Handle the DragDrop event to reorder records in the data source.
C#private void Behavior_DragOver(object sender, DragOverEventArgs e) {
DragOverGridEventArgs args = DragOverGridEventArgs.GetDragOverGridEventArgs(e);
e.InsertType = args.InsertType;
e.InsertIndicatorLocation = args.InsertIndicatorLocation;
e.Action = args.Action;
Cursor.Current = args.Cursor;
args.Handled = true;
}
private void Behavior_DragDrop(object sender, DevExpress.Utils.DragDrop.DragDropEventArgs e) {
GridView targetGrid = e.Target as GridView;
GridView sourceGrid = e.Source as GridView;
//...
sourceTable.Rows.Remove(oldRow);
sourceTable.Rows.InsertAt(newRow, newRowIndex);
//...
}
The following link contains a complete example: How to reorder grid rows by drag and drop
Drag rows between detail Views in the Data Grid
- Attach Drag-and-Drop Behavior to the master View.
- Use the ViewRegistered event to attach Drag-and-Drop Behavior to detail Views. To detach the Behavior, use the ViewRemoved event.
- Handle the DragDrop event of the Behavior attached to the master view to move the processed child row from the source detail view to the target detail view.
C#using DevExpress.Utils.DragDrop;
using DevExpress.XtraGrid.Views.Grid;
//
gridView1.OptionsBehavior.Editable = false;
gridView1.OptionsSelection.MultiSelect = true;
gridControl1.DataSource = CreateDataTable();
gridControl1.ViewRegistered += GridControl1_ViewRegistered;
gridControl1.ViewRemoved += GridControl1_ViewRemoved;
BehaviorManager behaviorManager = new BehaviorManager();
//
private void GridControl1_ViewRegistered(object sender, DevExpress.XtraGrid.ViewOperationEventArgs e) {
if (e.View.IsDetailView) {
behaviorManager.Attach<DragDropBehavior>(e.View,
behavior => {
behavior.DragDrop += Behavior_DragDrop;
behavior.DragOver += Behavior_DragOver;
});
}
}
private void GridControl1_ViewRemoved(object sender, DevExpress.XtraGrid.ViewOperationEventArgs e){
if (e.View.IsDetailView)
behaviorManager.Detach<DragDropBehavior>(e.View);
}
private void GridControlBehavior_DragOver(object sender, DragOverEventArgs e){
DragOverGridEventArgs args = DragOverGridEventArgs.GetDragOverGridEventArgs(e);
e.InsertType = args.InsertType;
e.InsertIndicatorLocation = args.InsertIndicatorLocation;
e.Action = args.Action;
Cursor.Current = args.Cursor;
args.Handled = true;
}
private void Behavior_DragDrop(object sender, DragDropEventArgs e) {
GridView masterView = e.Source as GridView;
// Cast the event arguments to the DragDropGridEventArgs type
// or call the static (Shared in VB) DragDropGridEventArgs.GetDragDropGridEventArgs method
// to get grid-specific event arguments.
DragDropGridEventArgs realArgs = (DragDropGridEventArgs)e;
GridView sourceView = realArgs.Source as GridView;
GridView targetView = realArgs.Target as GridView;
//
var view1 = gridControl.GetViewAt(gridControl.PointToClient(e.Location));
if (sourceView != null && targetView != null) {
// Get the processed child row's parent ID.
var newParentId = masterView.GetRowCellValue(targetView.SourceRowHandle, "Id");
foreach (DataRowView dataRow in realArgs.DataRows) {
// Update the processed child row's parent ID.
dataRow.Row["ParentId"] = newParentId;
}
e.Handled = true;
}
}
//
DataTable masterTable;
public DataTable CreateDataTable() {
masterTable = new DataTable();
masterTable.Columns.Add("Id", typeof(int));
masterTable.Columns.Add("Name");
masterTable.Columns.Add("IsActive", typeof(bool));
masterTable.Columns.Add("OrderCount", typeof(int));
masterTable.Columns.Add("RegistrationDate", typeof(DateTime));
for (int i = 0; i < 10; i++) {
masterTable.Rows.Add(i, "Name" + i, i % 2 == 0, i * 10, DateTime.Now.AddDays(i));
}
//
DataTable childTable = new DataTable();
childTable.Columns.Add("ParentId", typeof(int));
childTable.Columns.Add("Id", typeof(int));
childTable.Columns.Add("Name");
for (int i = 0; i < 20; i++) {
childTable.Rows.Add(i % 10, i, "Name" + i);
}
//
DataSet set = new DataSet();
set.Tables.Add(masterTable);
set.Tables.Add(childTable);
set.Relations.Add(masterTable.Columns["Id"], childTable.Columns["ParentId"]);
return masterTable;
}
Drag data from the Data Grid (GridView) to the Scheduler control
Use the standard .NET drag-and-drop engine and the SchedulerControl's PrepareDragData event.
See the following link for a complete example:
How to drag appointments from GridView and drop them onto the Scheduler Control using SchedulerDragData
Drag a grid cell to ListBoxControl and vice versa
To accomplish this task, you can use our Drag-and-Drop Behavior.
To change the preview image and show only a specific cell, handle the DragDropEvents.BeginDragDrop event and modify the image.
Use the DragDropEventArgs.Location property together with GridView.CalcHitInfo in the DragDrop event handler to locate the cell. Then, use the GridView.SetRowCellValue method with the GridHitInfo.Column and GridHitInfo.RowHandle properties to set a value.
C# behaviorManager1.Attach<DragDropBehavior>(listBoxControl1, behavior =>
{
behavior.Properties.AllowDrop = true;
behavior.Properties.InsertIndicatorVisible = true;
behavior.Properties.PreviewVisible = true;
behavior.DragDrop += Behavior_DragDrop;
});
behaviorManager1.Attach<DragDropBehavior>(gridView1, behavior =>
{
behavior.Properties.AllowDrop = true;
behavior.Properties.InsertIndicatorVisible = true;
behavior.Properties.PreviewVisible = true;
behavior.DragDrop += Behavior_DragDrop1;
behavior.BeginDragDrop += Behavior_BeginDragDrop;
});
...
private void Behavior_BeginDragDrop(object sender, BeginDragDropEventArgs e)
{
GridControl gc = GetChildAtPoint(PointToClient(MousePosition)) as GridControl;
if (gc == null) return;
Point gcPoint = gc.PointToClient(MousePosition);
GridView currentView = gc.GetViewAt(gcPoint) as GridView;
GridViewInfo viewInfo = currentView.GetViewInfo() as GridViewInfo;
GridHitInfo gridHitInfo = currentView.CalcHitInfo(gcPoint);
if (gridHitInfo == null) return;
if (gridHitInfo.InRowCell)
{
GridColumnInfoArgs currentColumnInfo = viewInfo.ColumnsInfo[gridHitInfo.Column];
int currentColumnWidth = currentColumnInfo.Bounds.Width;
int indicatorWidth = viewInfo.ViewRects.IndicatorWidth;
Bitmap newPreview = new Bitmap(currentColumnWidth, e.PreviewImage.Height);
using (Graphics graphics = Graphics.FromImage(newPreview))
graphics.DrawImage(e.PreviewImage, new Rectangle(0, 0, currentColumnWidth - indicatorWidth, e.PreviewImage.Height), new Rectangle(currentColumnInfo.Bounds.X, 0, currentColumnWidth, e.PreviewImage.Height), GraphicsUnit.Pixel);
e.PreviewImage.Dispose();
e.PreviewImage = newPreview;
_gridViewPoint = MousePosition;
}
}
private Point _gridViewPoint = Point.Empty;
private void Behavior_DragDrop(object sender, DragDropEventArgs e)
{
GridView srcView = e.Source as GridView;
ListBoxControl targetControl = e.Target as ListBoxControl;
GridHitInfo hitInfo = srcView.CalcHitInfo(srcView.GridControl.PointToClient(_gridViewPoint));
_gridViewPoint = Point.Empty;
if (hitInfo == null) return;
if (hitInfo.InRowCell)
{
object cellValue = srcView.GetRowCellValue(hitInfo.RowHandle, hitInfo.Column);
if (cellValue != null)
targetControl.Items.Add(cellValue);
}
}
private void Behavior_DragDrop1(object sender, DragDropEventArgs e)
{
GridView currentView = e.Target as GridView;
Point gcPoint = currentView.GridControl.PointToClient(e.Location);
GridHitInfo hitInfo = currentView.CalcHitInfo(gcPoint);
ListBoxControl srcControl = e.Source as ListBoxControl;
if (hitInfo.InRowCell == true && srcControl != null)
{
GridColumn column = hitInfo.Column;
int RowHandle = hitInfo.RowHandle;
var data = e.Data as List<object>;
var dataValue = data[0];
currentView.SetRowCellValue(RowHandle, column, dataValue);
e.Handled = true;
}
}
Forbid drag operation for specific groups (nodes in TreeList)
To forbid drag options in specific groups (nodes), do the following:
- Attach the Drag-and-Drop Behavior to the GridView or TreeList.
- Handle the DragOver event to display the insert indicator and update the mouse pointer.
In the example below, we demonstrated how to forbid drag operations for the ID group with the 1 value (for the Data Grid) or the node with the identifier equal to 1 (for the TreeList).
C#// Data Grid
private void Behavior_DragOver(object sender, DragOverEventArgs e) {
e.Default();
GridView gridView = e.Target as GridView;
GridHitInfo info = gridView.CalcHitInfo(gridView.GridControl.PointToClient(e.Location));
int groupValue = 1;
if((info.InGroupRow && (int)gridView.GetGroupRowValue(info.RowHandle) == groupValue) || // check group row
info.InDataRow && (int)gridView.GetRowCellValue(info.RowHandle, "ID") == groupValue) { // check child rows in the ID group
e.InsertIndicatorSize = new Size(0, 0);
e.Action = DragDropActions.None;
e.Cursor = Cursors.No;
}
}
// TreeList
private void Behavior_DragOver(object sender, DragOverEventArgs e) {
e.Default();
TreeList treeList = e.Target as TreeList;
var treeListNode = treeList.CalcHitInfo(treeList.PointToClient(e.Location)).Node;
int nodeKeyValue = 1;
if(treeListNode != null && (
((int)treeListNode.GetValue("ID") == nodeKeyValue && e.InsertType == InsertType.AsChild) || // check parent node
treeListNode.HasAsParent(treeList.FindNodeByKeyID(nodeKeyValue)))) { // check child nodes
e.InsertIndicatorSize = new Size(0, 0);
e.Action = DragDropActions.None;
e.Cursor = Cursors.No;
}
}
}