Skip to main content

DevExpress v24.2 Update — Your Feedback Matters

Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

How to: Drag XtraGrid rows to the XtraTreeList

  • 9 minutes to read

Tip

Starting with version 17.2, you can attach the Drag-and-Drop Behavior to controls (for example, XtraGrid, XtraTreeList) to enable drag-drop operations. An example that uses the Drag-and-Drop Behavior is available at GitHub: Drag-and-Drop Grid Rows to the TreeList.

Run Demo: Drag Nodes to ListBox Run Demo: Drag Rows Between Grids

The following example demonstrates even-based implementation of drag-drop operations:

  1. Handle the grid’s MouseDown event to obtain the clicked data row.
  2. Set the GridView’s OptionsBehavior.EditorShowMode option to EditorShowMode.MouseUp or EditorShowMode.Click to prevent a cell editor from being opened on the MouseDown event.
  3. Handle the grid’s MouseMove event to initialize a drag operation.
  • Set the TreeList’s AllowDrop property to true to allow the TreeList to accept data that a user drags onto it.
  • Handle the TreeList’s DragDrop event to append a new node. Use the TreeList.AppendNode. The event handler uses the TreeList.GetDXDragEventArgs extension method to obtain the following event arguments:

    • TargetNode — specifies the node onto which the grid row is dropped.
    • DragInsertPosition — specifies how to insert the node (as a child node, before the target node, or after the target node).

In this example, the TreeList is bound to a BindingList<T>.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraTreeList;
using DevExpress.XtraGrid;
using DevExpress.XtraTreeList.Nodes;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraEditors;


namespace DragAndDropRows {
    public partial class Form1 : XtraForm {

        GridHitInfo hitInfo = null;
        BindingList<Person> gridDataSource = new BindingList<Person>();

        public Form1() {
            InitializeComponent();
            InitGrid();
            InitTreeList();
        }

        void InitGrid() {
            gridDataSource.Add(new Person("John", "Smith", "USA"));
            gridDataSource.Add(new Person("Michael", "Suyama", "UK"));
            gridDataSource.Add(new Person("Laura", "Callahan", "UK"));
            gridDataSource.Add(new Person("Gerard", "Blain", "France"));
            gridDataSource.Add(new Person("Sergio", "Rubini", "Italy"));
            gridDataSource.Add(new Person("Andrew", "Fuller", "USA"));
            gridControl.DataSource = gridDataSource;
            // Enable drag-and-drop operations within the GridView.
            gridView.OptionsBehavior.EditorShowMode = DevExpress.Utils.EditorShowMode.Click;
        }

        void InitTreeList() {
            treeList.DataSource = new BindingList<PersonEx>() ;
            // Specify the data source field that contains node identifiers.
            treeList.KeyFieldName = "ID";
            // Specify the data source field that contains parent node identifiers.
            treeList.ParentFieldName = "ParentID";
            // Allow the control to accept data that a user drags onto it.
            treeList.AllowDrop = true;
        }

        private void gridControl_MouseDown(object sender, MouseEventArgs e) {
            hitInfo = gridView.CalcHitInfo(new Point(e.X, e.Y));
        }

        // Initialize a drag-and-drop operation.
        private void gridControl_MouseMove(object sender, MouseEventArgs e) {
            if (hitInfo == null) return;
            if (e.Button != MouseButtons.Left) return;
            Rectangle dragRect = new Rectangle(new Point(
                hitInfo.HitPoint.X - SystemInformation.DragSize.Width / 2,
                hitInfo.HitPoint.Y - SystemInformation.DragSize.Height / 2), SystemInformation.DragSize);
            if (!(hitInfo.RowHandle == GridControl.InvalidRowHandle) && !dragRect.Contains(new Point(e.X, e.Y))) {
                Object data = gridView.GetRow(hitInfo.RowHandle);
                gridControl.DoDragDrop(data, DragDropEffects.Copy);
            }

        }

        private void treeList_DragEnter(object sender, DragEventArgs e) {
            e.Effect = DragDropEffects.Copy;
        }

        // Add a node to the TreeList when a grid row is dropped.
        private void treeList_DragDrop(object sender, DragEventArgs e) {
            // Get extended arguments of the drag event.
            DXDragEventArgs args = treeList.GetDXDragEventArgs(e);
            // Get how a node is inserted (as a child, before or after a node, or at the end of the node collection).
            DragInsertPosition position = args.DragInsertPosition;
            Person dataRow = e.Data.GetData(typeof(DragAndDropRows.Person)) as Person;
            if (dataRow == null) return;
            int parentID = (int)treeList.RootValue;
            // Get the node over which the row is dropped.
            TreeListNode node = args.TargetNode;
            // Add a node at the root level.
            if (node == null) {
                treeList.AppendNode((new PersonEx(dataRow, parentID)).ToArray(), null);
            }
            else {
                // Add a child node to the target node.
                if (position == DragInsertPosition.AsChild) {
                    parentID = Convert.ToInt32(node.GetValue("ID"));
                    Object[] targetObject = (new PersonEx(dataRow, parentID)).ToArray(); 
                    treeList.AppendNode(targetObject, node);
                }
                // Insert a node before the target node.
                if (position == DragInsertPosition.Before) {
                    parentID = Convert.ToInt32(node.GetValue("ParentID"));
                    Object[] targetObject = (new PersonEx(dataRow, parentID)).ToArray();
                    TreeListNode newNode = treeList.AppendNode(targetObject, node.ParentNode);
                    int targetPosition;
                    if (node.ParentNode == null)
                        targetPosition = treeList.Nodes.IndexOf(node);
                    else targetPosition = node.ParentNode.Nodes.IndexOf(node);
                    treeList.SetNodeIndex(newNode, targetPosition);
                }
                node.Expanded = true;
            }
        }

        private void treeList_DragOver(object sender, DragEventArgs e) {
            e.Effect = DragDropEffects.Copy;
        }

    }
}
See Also