본문 바로가기

worklog/C#

[C#/Devexpress/Winform] GridControl의 아이템을 Drag & Drop 하여 다른 Control에 전달하는 방법 소개

GridControl의 아이템을 Drag & Drop 하여 다른 Control에 전달하는 방법 소개

  • 샘플 코드 시나리오
    1. Form을 Load할 때, GridControl에 데이터 Set
    2. GridControl의 아이템을 클릭 후 Drag하여 TextEdit에 Drop
    3. 아이템을 Drop한 TextEdit에 클릭한 GridControl의 아이템 정보 Set 
  • 프로젝트 환경
    • .Net Framework 4.5.2
    • Devexpress 21.1

 

Step 1. 아래와 같이 UI를 배치한다. Devexpress의 GridContro와 TextEdit을 배치

컨트롤 배치 화면

Step 2. 소스코드 작성

1. Form의 Load 이벤트 추가 

Form이 Load될 때, 컨트롤들의 초기화 로직을 구현합니다. 

GridControl에는 임시로 Drag & Drop으로 전달할 데이터를 셋팅해주고

Editable 상태이면 Drag를 할 수 없어서 Editable 속성을 false로 설정해줍니다. 

 

TextEdit에는 Drop을 받아야하기 때문에 AllowDrop 속성을 true로 설정합니다. 

public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            SetUpGridControl();
            SetUpTextEdit();
        }

        void SetUpGridControl()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[]
            {
                new DataColumn("NAME", typeof(string)),
            });

            dt.Rows.Add("MK");
            dt.Rows.Add("엠케이");
            dt.Rows.Add("엠케이월드");

            gridControl1.DataSource = dt;
            gridView1.OptionsBehavior.Editable = false;

            gridView1.MouseDown += GridView1_MouseDown;
            gridView1.MouseMove += GridView1_MouseMove;
        }

        void SetUpTextEdit()
        {
            textEdit1.AllowDrop = true;

            textEdit1.DragEnter += TextEdit1_DragEnter;
            textEdit1.DragOver += TextEdit1_DragOver;
            textEdit1.DragDrop += TextEdit1_DragDrop;
        }

2. GridControl의 MouseDown / MouseMove 이벤트 추가

GridControl에서 Drag & Drop을 수행할 때 필요한 MouseDown과 MouseMove 이벤트를 추가합니다. 

MouseDown에서는 전달할 데이터를 클릭했을 때, Hit된 정보를 멤버 변수에 저장하고

MouseMove에서는 Hit된 위치로부터 DragSize만큼 벗어나게 되면 DoDragDrop을 수행하게 됩니다. 

 

 

GridHitInfo hitInfo;
        private void GridView1_MouseDown(object sender, MouseEventArgs e)
        {
            var view = sender as GridView;
            hitInfo = null;

            // GridControl 안에서 Hit 된 정보를 가져온다. 
            GridHitInfo hit = view.CalcHitInfo(e.X, e.Y);
            if (Control.ModifierKeys != Keys.None)
            {
                return;
            }

            // 마우스 좌클릭 & GridControl의 Row 안에서 클릭되었으면 Hit 정보를 맴버 변수에 저장
            if (e.Button == MouseButtons.Left && hit.RowHandle >= 0)
            {
                hitInfo = hit;
            }
        }


        private void GridView1_MouseMove(object sender, MouseEventArgs e)
        {
            GridView view = sender as GridView;
            if (e.Button != MouseButtons.Left || hitInfo == null)
            {
                return;
            }

            Size dragSize = SystemInformation.DragSize;
            Rectangle dragRect = new Rectangle(
                hitInfo.HitPoint.X - dragSize.Width / 2,
                hitInfo.HitPoint.Y - dragSize.Height / 2,
                dragSize.Width,
                dragSize.Height);

            // Hit 포인트에서 DragSize를 벗어나면 (즉, 드레그가 되었는지 판단되면)
            // 저장한 Hit 정보에서 선택된 Row 정보를 DoDragDrop 함수를 통해 전달. 
            if (!dragRect.Contains(e.X, e.Y))
            {
                var row = view.GetRow(hitInfo.RowHandle);
                // DoDragDrop이 호출되고 Mouse Up 되기 전까지 DoDragDrop이 끝나지 않음
                view.GridControl.DoDragDrop(row, DragDropEffects.Copy);

                // DoDragDrop이 끝났기 때문에 Hit 정보 초기화 
                hitInfo = null;
                DevExpress.Utils.DXMouseEventArgs.GetMouseArgs(e).Handled = true;
            }
        }

3. TextEdit의 DragEnter / DragOver / DragDrop 이벤트 추가

아이템을 Drag하여 TextEdit으로 들어오면 DragEnter & DragOver 이벤트가 발생하고 

아이템을 Drop하면 DragDrop이벤트가 발생하는데 DoDragDrop 함수를 통해 전달한 데이터를 TextEdit의 Text에 셋합니다.

private void TextEdit1_DragEnter(object sender, DragEventArgs e)
        {
            DataObject doDrop = (DataObject)e.Data;
            e.Effect = DragDropEffects.Copy;
        }


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

        private void TextEdit1_DragDrop(object sender, DragEventArgs e)
        {
            DataObject doClipboard = (DataObject)e.Data;
            // DragEventArgs의 Data의  데이터 타입이 DataRowView이면, 해당 정보를 TextEdit에 저장
            if (doClipboard.GetDataPresent(typeof(DataRowView)))
            {
                DataRowView row = doClipboard.GetData(typeof(DataRowView)) as DataRowView;
                textEdit1.Text = row[0].ToString();
            }
        }

 

 

 

 

 전체 STEP의 소스코드 내용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace Test1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            SetUpGridControl();
            SetUpTextEdit();
        }
 
        void SetUpGridControl()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[]
            {
                new DataColumn("NAME"typeof(string)),
            });
 
            dt.Rows.Add("MK");
            dt.Rows.Add("엠케이");
            dt.Rows.Add("엠케이월드");
 
            gridControl1.DataSource = dt;
            gridView1.OptionsBehavior.Editable = false;
 
            gridView1.MouseDown += GridView1_MouseDown;
            gridView1.MouseMove += GridView1_MouseMove;
        }
 
        void SetUpTextEdit()
        {
            textEdit1.AllowDrop = true;
 
            textEdit1.DragEnter += TextEdit1_DragEnter;
            textEdit1.DragOver += TextEdit1_DragOver;
            textEdit1.DragDrop += TextEdit1_DragDrop;
        }
 
 
        GridHitInfo hitInfo;
        private void GridView1_MouseDown(object sender, MouseEventArgs e)
        {
            var view = sender as GridView;
            hitInfo = null;
 
            // GridControl 안에서 Hit 된 정보를 가져온다. 
            GridHitInfo hit = view.CalcHitInfo(e.X, e.Y);
            if (Control.ModifierKeys != Keys.None)
            {
                return;
            }
 
            // 마우스 좌클릭 & GridControl의 Row 안에서 클릭되었으면 Hit 정보를 맴버 변수에 저장
            if (e.Button == MouseButtons.Left && hit.RowHandle >= 0)
            {
                hitInfo = hit;
            }
        }
 
 
        private void GridView1_MouseMove(object sender, MouseEventArgs e)
        {
            GridView view = sender as GridView;
            if (e.Button != MouseButtons.Left || hitInfo == null)
            {
                return;
            }
 
            Size dragSize = SystemInformation.DragSize;
            Rectangle dragRect = new Rectangle(
                hitInfo.HitPoint.X - dragSize.Width / 2,
                hitInfo.HitPoint.Y - dragSize.Height / 2,
                dragSize.Width,
                dragSize.Height);
 
            // Hit 포인트에서 DragSize를 벗어나면 (즉, 드레그가 되었는지 판단되면)
            // 저장한 Hit 정보에서 선택된 Row 정보를 DoDragDrop 함수를 통해 전달. 
            if (!dragRect.Contains(e.X, e.Y))
            {
                var row = view.GetRow(hitInfo.RowHandle);
                // DoDragDrop이 호출되고 Mouse Up 되기 전까지 DoDragDrop이 끝나지 않음
                view.GridControl.DoDragDrop(row, DragDropEffects.Copy);
 
                // DoDragDrop이 끝났기 때문에 Hit 정보 초기화 
                hitInfo = null;
                DevExpress.Utils.DXMouseEventArgs.GetMouseArgs(e).Handled = true;
            }
        }
 
        private void TextEdit1_DragEnter(object sender, DragEventArgs e)
        {
            DataObject doDrop = (DataObject)e.Data;
            e.Effect = DragDropEffects.Copy;
        }


        private void TextEdit1_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }
 
        private void TextEdit1_DragDrop(object sender, DragEventArgs e)
        {
            DataObject doClipboard = (DataObject)e.Data;
            // DragEventArgs의 Data의  데이터 타입이 DataRowView이면, 해당 정보를 TextEdit에 저장
            if (doClipboard.GetDataPresent(typeof(DataRowView)))
            {
                DataRowView row = doClipboard.GetData(typeof(DataRowView)) as DataRowView;
                textEdit1.Text = row[0].ToString();
            }
        }
        
 
       
 
 
    }
}
cs
3. 실행 결과
샘플 코드 실행 결과

 

 

 

 

 

'worklog > C#' 카테고리의 다른 글

Thread  (0) 2018.08.25
C# 버전 별 추가된 기능  (0) 2018.08.19
Call by Reference (param, ref, out)  (0) 2018.06.30
Environment 클래스  (0) 2018.06.30
What the C or C++ Programmer Needs to Know About C# and the .NET Framework  (0) 2018.06.30