windowsforms-3021-controls-and-libraries-tree-list-feature-center-drag-and-drop-how-to-drag-xtragrid-rows-to-the-xtratreelist.md
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:
EditorShowMode.MouseUp or EditorShowMode.Click to prevent a cell editor from being opened on the MouseDown event.TreeList.GetDXDragEventArgs extension method to obtain the following event arguments: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;
}
}
}
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 };
}
}
}
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());
}
}
}
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
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
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