How to: Drag XtraGrid rows to the XtraTreeList

  • 9 minutes to read

To support drag operations from the GridControl to the TreeList, do the following:

  • handle the GridControl's MouseDown event — to obtain the clicked data row. Set the GridView's EditorShowMode option to MouseUp or Click to prevent a cell editor from being opened on the MouseDown event.
  • handle the GridControl's MouseMove event — to initialize a drag operation.
  • set the TreeList's AllowDrop property to true — to allow the control to accept data that a user drags onto it.
  • handle the TreeList's DragDrop event — to append a new node (see AppendNode). The handler uses the TreeList.GetDXDragEventArgs extension method to obtain the following extended event arguments:

    • TargetNode — specifies the node onto which the row is dropped.
    • DragInsertPosition — specifies how a node is inserted (as a child, before or after a node, or at the end of the list).

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;
        }

    }
}
TIP

Starting with version 17.2, you can attach the Drag-and-Drop Behavior to controls to enable drag operations. An example that uses the Drag-and-Drop Behavior is available at https://github.com/DevExpress-Examples/how-to-drag-and-drop-gridcontrol-rows-to-the-treelist-t202760.

See Also