I'm using DevExpress controls in my WinForms project.
I need to re-order the group rows(include their details) by drag and drop using BehaviorManager(in addition to re-ordering the rows inside the details).
For drag&drop rows I wrote following codes:
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, DragDropEventArgs e)
{
GridView targetGrid = e.Target as GridView;
GridView sourceGrid = e.Source as GridView;
if (e.Action == DragDropActions.None || targetGrid != sourceGrid)
return;
DataTable sourceTable = sourceGrid.GridControl.DataSource as DataTable;
Point hitPoint = targetGrid.GridControl.PointToClient(Cursor.Position);
GridHitInfo hitInfo = targetGrid.CalcHitInfo(hitPoint);
int[] sourceHandles = e.GetData<int[]>();
int targetRowHandle = hitInfo.RowHandle;
int targetRowIndex = targetGrid.GetDataSourceRowIndex(targetRowHandle);
List<DataRow> draggedRows = new List<DataRow>();
foreach (int sourceHandle in sourceHandles) {
int oldRowIndex = sourceGrid.GetDataSourceRowIndex(sourceHandle);
DataRow oldRow = sourceTable.Rows[oldRowIndex];
draggedRows.Add(oldRow);
}
int newRowIndex;
switch (e.InsertType) {
case InsertType.Before:
newRowIndex = targetRowIndex > sourceHandles[sourceHandles.Length - 1]
? targetRowIndex - 1 : targetRowIndex;
for (int i = draggedRows.Count - 1; i >= 0; i--) {
DataRow oldRow = draggedRows[i];
DataRow newRow = sourceTable.NewRow();
newRow.ItemArray = oldRow.ItemArray;
sourceTable.Rows.Remove(oldRow);
sourceTable.Rows.InsertAt(newRow, newRowIndex);
}
break;
case InsertType.After:
newRowIndex = targetRowIndex < sourceHandles[0]
? targetRowIndex + 1 : targetRowIndex;
for (int i = 0; i < draggedRows.Count; i++) {
DataRow oldRow = draggedRows[i];
DataRow newRow = sourceTable.NewRow();
newRow.ItemArray = oldRow.ItemArray;
sourceTable.Rows.Remove(oldRow);
sourceTable.Rows.InsertAt(newRow, newRowIndex);
}
break;
default:
newRowIndex = -1;
break;
}
int insertedIndex = targetGrid.GetRowHandle(newRowIndex);
targetGrid.FocusedRowHandle = insertedIndex;
targetGrid.SelectRow(targetGrid.FocusedRowHandle);
}
For example I want to replace Level3 and Level6 group rows position by drag & drop.

This answer uses a custom
GridViewExclass inherited fromGridViewwhich allows the objective of reordering grouped rows using drag & drop to be achieved in a clean manner without a lot of code mixed in with the main form. Your post and additional comments state two requirements, and I have added a third goal to make the look and feel similar to the drag drop functionality that already exists for the records.This custom version is simply swapped out manually in the Designer.cs file.
The feedback line in this example is blue for "Before Target Row" and red for "After Target Row".
Groups that are expanded before an operation remain in that state.
GridViewEx - The demo project is available to clone from GitHub.
GridViewExmaintains its ownGroupDragDropStateto avoid potential conflicts withBehaviorManageroperations.The
Dragstate is entered if the mouse-down cursor travels more than 10 positions in any direction.Drag Feedback
Entering the drag state takes a screenshot of the clicked row. To ensure the proper operation of the
Graphics.CopyFromScreenmethod, the appconfig.cs has been modified to per-screen DPI awareness.appconfig.cs
GridViewEx.cs
This image is assigned to the
BackgroundImageof the_dragFeedbackLabelmember which is a borderless form that can be drawn outside the rectangle of the main form. When visible, this form tracks the mouse cursor movement by means of aMessageFilterinterceptingWM_MOUSEMOVEmessages.The row dividers are drawn by handling the
GridView.CustomDrawGroupRowevent.When the
DropBelowvalue toggles at the midpoint of the drag over or when the target row changes, the affected row(s) need to be redrawn.OnDrop
The
ItemsArrayfor the removed records is stashed in a dictionary to allow reassignment before inserting the sameDataRowinstance at a new index. Adjustments to the insert operation are made depending on the value of theDropBelowboolean which was set in theMouseMovehandler.Misc
GridViewExtakes a blanket approach to enabling custom sort only, and preliminary testing shows that drag drop in its present form works the same for the Keyword grouping as it does for Level.