Back to Devexpress

How to: Drag XtraGrid rows to the XtraTreeList

windowsforms-3021-controls-and-libraries-tree-list-feature-center-drag-and-drop-how-to-drag-xtragrid-rows-to-the-xtratreelist.md

latest18.4 KB
Original Source

How to: Drag XtraGrid rows to the XtraTreeList

  • May 06, 2024
  • 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:

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

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

    }
}
csharp
using System;

namespace DragAndDropRows {
    public class Person {
        string firstName;
        string lastName;
        string country;

        public Person() { }
        public Person(string firstName, string lastName, string country) {
            this.firstName = firstName;
            this.lastName = lastName;
            this.country = country;
        }
        public string FirstName {
            get { return firstName; }
            set { firstName = value; }
        }

        public string LastName {
            get { return lastName; }
            set { lastName = value; }
        }

        public string Country {
            get { return country; }
            set { country = value; }
        }

    }

    public class PersonEx : Person {
        int id;
        int parentID;
        static int counter = 1;
        public PersonEx() { }
        public PersonEx(string firstName, string lastName, string country, int parentID)
            : base(firstName, lastName, country) {
            this.parentID = parentID;
            id = counter++;
        }

        public PersonEx(Person person, int parentID)
            : this(person.FirstName, person.LastName, person.Country, parentID) {
        }

        public int ID {
            get { return id; }
            set { id = value; }
        }
        public int ParentID {
            get { return parentID; }
            set { parentID = value; }
        }
        public Object[] ToArray() {
            return new Object[] {ID, ParentID, FirstName, LastName, Country };
        }
    }
}
csharp
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using DevExpress.LookAndFeel;

namespace DragAndDropRows
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            DevExpress.Skins.SkinManager.EnableFormSkins();
            DevExpress.UserSkins.BonusSkins.Register();
            UserLookAndFeel.Default.SetSkinStyle("DevExpress Style");

            Application.Run(new Form1());
        }
    }
}
vb
Imports System
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports DevExpress.LookAndFeel

Namespace DragAndDropRows
    Friend NotInheritable Class Program

        Private Sub New()
        End Sub

        ''' <summary>
        ''' The main entry point for the application.
        ''' </summary>
        <STAThread>
        Shared Sub Main()
            Application.EnableVisualStyles()
            Application.SetCompatibleTextRenderingDefault(False)

            DevExpress.Skins.SkinManager.EnableFormSkins()
            DevExpress.UserSkins.BonusSkins.Register()
            UserLookAndFeel.Default.SetSkinStyle("DevExpress Style")

            Application.Run(New Form1())
        End Sub
    End Class
End Namespace
vb
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports DevExpress.XtraGrid.Views.Grid.ViewInfo
Imports DevExpress.XtraTreeList
Imports DevExpress.XtraGrid
Imports DevExpress.XtraTreeList.Nodes
Imports DevExpress.XtraTreeList.Columns
Imports DevExpress.XtraEditors

Namespace DragAndDropRows
    Partial Public Class Form1
        Inherits XtraForm

        Private hitInfo As GridHitInfo = Nothing
        Private gridDataSource As New BindingList(Of Person)()

        Public Sub New()
            InitializeComponent()
            InitGrid()
            InitTreeList()
        End Sub

        Private Sub 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
        End Sub

        Private Sub InitTreeList()
            treeList.DataSource = New BindingList(Of 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
        End Sub

        Private Sub gridControl_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles gridControl.MouseDown
            hitInfo = gridView.CalcHitInfo(New Point(e.X, e.Y))
        End Sub

        ' Initialize a drag-and-drop operation.
        Private Sub gridControl_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles gridControl.MouseMove
            If hitInfo Is Nothing Then
                Return
            End If
            If e.Button <> MouseButtons.Left Then
                Return
            End If
            Dim dragRect As New Rectangle(New Point(hitInfo.HitPoint.X - SystemInformation.DragSize.Width \ 2, hitInfo.HitPoint.Y - SystemInformation.DragSize.Height \ 2), SystemInformation.DragSize)
            If Not (hitInfo.RowHandle = gridControl.InvalidRowHandle) AndAlso (Not dragRect.Contains(New Point(e.X, e.Y))) Then
                Dim data As Object = gridView.GetRow(hitInfo.RowHandle)
                gridControl.DoDragDrop(data, DragDropEffects.Copy)
            End If

        End Sub

        Private Sub treeList_DragEnter(ByVal sender As Object, ByVal e As DragEventArgs) Handles treeList.DragEnter
            e.Effect = DragDropEffects.Copy
        End Sub

        ' Add a node to the TreeList when a grid row is dropped.
        Private Sub treeList_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs) Handles treeList.DragDrop
            ' Get extended arguments of the drag event.
            Dim args As DXDragEventArgs = 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).
            Dim position As DragInsertPosition = args.DragInsertPosition
            Dim dataRow As Person = TryCast(e.Data.GetData(GetType(DragAndDropRows.Person)), Person)
            If dataRow Is Nothing Then
                Return
            End If
            Dim parentID As Integer = DirectCast(treeList.RootValue, Integer)
            ' Get the node over which the row is dropped.
            Dim node As TreeListNode = args.TargetNode
            ' Add a node at the root level.
            If node Is Nothing Then
                Dim parentNode As TreeListNode = Nothing
                treeList.AppendNode(New PersonEx(dataRow, parentID).ToArray(), parentNode)
            Else
                ' Add a child node to the target node.
                If position = DragInsertPosition.AsChild Then
                    parentID = Convert.ToInt32(node.GetValue("ID"))
                    Dim targetObject() As Object = (New PersonEx(dataRow, parentID)).ToArray()
                    treeList.AppendNode(targetObject, node)
                End If
                ' Insert a node before the target node.
                If position = DragInsertPosition.Before Then
                    parentID = Convert.ToInt32(node.GetValue("ParentID"))
                    Dim targetObject() As Object = (New PersonEx(dataRow, parentID)).ToArray()
                    Dim newNode As TreeListNode = treeList.AppendNode(targetObject, node.ParentNode)
                    Dim targetPosition As Integer
                    If node.ParentNode Is Nothing Then
                        targetPosition = treeList.Nodes.IndexOf(node)
                    Else
                        targetPosition = node.ParentNode.Nodes.IndexOf(node)
                    End If
                    treeList.SetNodeIndex(newNode, targetPosition)
                End If
                node.Expanded = True
            End If
        End Sub

        Private Sub treeList_DragOver(ByVal sender As Object, ByVal e As DragEventArgs) Handles treeList.DragOver
            e.Effect = DragDropEffects.Copy
        End Sub

    End Class
End Namespace
vb
Imports System

Namespace DragAndDropRows
    Public Class Person
        Private firstName1 As String
        Private lastName1 As String
        Private country1 As String

        Public Sub New()
        End Sub
        Public Sub New(ByVal firstName As String, ByVal lastName As String, ByVal country As String)
            Me.firstName1 = firstName
            Me.lastName1 = lastName
            Me.country1 = country
        End Sub
        Public Property FirstName() As String
            Get
                Return firstName1
            End Get
            Set(ByVal value As String)
                firstName1 = value
            End Set
        End Property

        Public Property LastName() As String
            Get
                Return lastName1
            End Get
            Set(ByVal value As String)
                lastName1 = value
            End Set
        End Property

        Public Property Country() As String
            Get
                Return country1
            End Get
            Set(ByVal value As String)
                country1 = value
            End Set
        End Property

    End Class

    Public Class PersonEx
        Inherits Person

        Private id1 As Integer
        Private parentID1 As Integer
        Private Shared counter As Integer = 1
        Public Sub New()
        End Sub
        Public Sub New(ByVal firstName As String, ByVal lastName As String, ByVal country As String, ByVal parentID As Integer)
            MyBase.New(firstName, lastName, country)
            Me.parentID1 = parentID
            id1 = counter
            counter += 1
        End Sub

        Public Sub New(ByVal person As Person, ByVal parentID As Integer)
            Me.New(person.FirstName, person.LastName, person.Country, parentID)
        End Sub

        Public Property ID() As Integer
            Get
                Return id1
            End Get
            Set(ByVal value As Integer)
                id1 = value
            End Set
        End Property
        Public Property ParentID() As Integer
            Get
                Return parentID1
            End Get
            Set(ByVal value As Integer)
                parentID1 = value
            End Set
        End Property
        Public Function ToArray() As Object()
            Return New Object() {ID, ParentID, FirstName, LastName, Country }
        End Function
    End Class
End Namespace

See Also

Drag-and-Drop Tree List Nodes