티스토리 뷰

C#/C# 강좌 Winform

Doridori C# 강의 2) 44. TreeView (File Copy)

꼬꼬마도리도리 2020. 4. 18. 23:02

======================================================

안녕하세요 Doridori 입니다.


원래 목표가 2주에 한 강의 인데 어찌어찌하다보니 한주를 건너뛰게 되었습니다. ㅜㅠ;;


평일에는 지방에 혼자 내려가 있다가 주말에 집에 와서 평일에 대충 만들어 놓은 내용을 정리하고 


예제만들고 강의만들고 하다보니 시간이 어렵네요 ^^;;;


저번주는 아이들이 자기들 잘때까지 같이 누워 있자고 해서 같이 누워 있다가 잠들어 버렸습니다. !!! 하하핫;;;;


어쨋든!! 


다 함께 화이팅 하시죠!! 아자!!


(이번강의는 시간 관계상 2개의 강의로 진행 하였는데 다음 강의는 차주에 바로 정리해서 올릴 예정 입니다.)

======================================================


44. TreeView (File Copy)

 

 

Source UI (1)) Study_44_TreeView (FileCopy) (1) (UI).zip

Soruce 전체 (1)) Study_44_TreeView (FileCopy) (1).zip

Soruce 전체 (2)) Study_44_TreeView (FileCopy) (2) (Logview, DirectoryInfo).zip


교재) 44. TreeView (File Copy).pdf










이번에 준비 한 내용은 TreeView에 관한 내용 입니다. 


프로그램을 만들다 보면 자주 사용되는 Control은 아니지만 특정 상황에서는 꼭 필요한 Control 이기도하고 구조상 새로운 용어들이 나오기 때문에 알아놓긴 해야 하는 내용들이라고 생각 합니다. 


2개정도의 강의로 파일은 백업 하는 프로그램을 만들어 보려고 하며 첫번째 강의는 TreeView에 대한 내용을 중점적으로 진행 하고 두번째 강의에는 나머지 내용들과 프로그램 마무리 까지 진행 할 예정 입니다. 


(두번째 강의 내용 까지 모두 추가 했습니다.!! (2020/04/18))

두번째 강의에서는 Directory를 검색하는 부분, LogView를 만드는 방법 정도를 정리 하였습니다. 


Tree 구조의 경우 노드라는 단어와 부모, 자식, 루트 정도는 알고 진행 하면 좋을 듯 합니다.



UI)


다른 Control의 경우 기존에 사용하던 것들 이기 때문에 그냥 사용하시면 될듯 하고 (여기까지 진행 하셨으면 기본적으로 사용 하는 Control은 거의 다 사용 했습니다. ^^;;) TreeView만 중점적으로 보시면 좋을 듯 합니다. 


Source나 Dest를 입력 받는 TextBox의 경우 Dialog 같은 걸 이용해도 좋을 듯 싶긴 했지만 간단하게 가져 갔습니다. 


프로그램 소스를 받으신 뒤에 개선해 보는것도 괜찮지 않을까 합니다. ^^;;




강의 1)


UI 작성 부분도 빼고 진행 했고 정리하고 나서 내용을 봤을때 그렇게 코드가 많은 내용이 아닌데 시간이 대략 30분 후반대의 시간이 나오네요. 


끝까지 진행 했으면 큰일 날 뻔 했습니다. ㅎㅎ (하면서 어느정도 시간이 걸릴지 감이 오게 된것 같기도 하네요)


연결 되는 강의는 내용은 다 만들어 놓았기 때문에 차주쯤에 바로 올리도록 하겠습니다. !!! 




강의 2)


한번에 만든 내용이라 추가해서 올렸습니다. 


Treeview 2강에서는 파일복사하는 부분, Directory를 찾는 부분, 프로그램에서 생기는 오류나 문제점들을 사용자에게 알려주기 위한 LogViewer를 만드는 법 정도의 내용을 담고 있습니다. 


엄청 새로울듯한 내용은 없지만 프로그램을 만드는데 필요한 자잘한 팁들을 애기했다고 생각 합니다. ^^;;







Source)


기존 소스는 삭제하고 Full Source로 새로 올렸습니다. ^^;;


(내용도 정리하고 . . . ㅎ)



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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
 
using Microsoft.VisualBasic.FileIO;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace treeview
{
    public partial class Form1 : Form
    {
        // Log Level을 지정 할 Enum
        enum enLogLevel
        {
            Info,
            Warning,            
            Error,
        }
        
        //Dictionary<string, string> dc = new Dictionary<string, string>();
 
        public Form1()
        {
            InitializeComponent();
        }
        
        
 
        #region Form Event
        /// <summary>
        /// TreeView 경로 Load Event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTreeLoad_Click(object sender, EventArgs e)
        {
            TreeViewLoadbyPath(tviewLocation, tboxSource.Text);
        }
 
        /// <summary>
        /// TreeNode 펼치기 버튼
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExtend_Click(object sender, EventArgs e)
        {
            if (tviewLocation.SelectedNode != null)
            {
                tviewLocation.SelectedNode.ExpandAll();   // 선택한 Node 부터 하위 노드를 펼침
            }
        }
 
        /// <summary>
        /// TreeNode 전체 닫기 (개인적으로 노드를 선택 할 경우 바로 앞에 하위 노드를 다 닫을 수 있기 때문에 선택 노드 닫기는 필요 없다고 생각 함)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCoolapse_Click(object sender, EventArgs e)
        {
            tviewLocation.CollapseAll();
        }
 
        /// <summary>
        /// TreeView를 더블 클릭 할 경우 ListBox에 Node 경로를 넣어 줌 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tviewLocation_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                string strSelectPath = tviewLocation.SelectedNode.FullPath;
 
                // 선택 노드가 lboxCommand에 있을 경우 중복 등록 하지 않음
                if (lboxCommand.Items.Contains(strSelectPath))
                {
                    Log(enLogLevel.Warning, "선택 한 Folder는 이미 Command 항목에 등록 되어 있습니다.");
                    return;
                }
 
                lboxCommand.Items.Add(tviewLocation.SelectedNode.FullPath);
                //dc.Add(tviewLocation.SelectedNode.FullPath, tviewLocation.SelectedNode.FullPath);   // Node 경로를 바로 넣어 놓기 때문에 굳이 Dic를 사용 할 필요가 없을 듯
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
 
        /// <summary>
        /// lboxCommand를 더블 클릭 했을 경우 lboxCommand에 선택 되어 있는 Item을 삭제
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lboxCommand_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            lboxCommand.Items.RemoveAt(lboxCommand.SelectedIndex);
            //dc.Remove(tviewLocation.SelectedNode.FullPath); // 삭제
        }
 
 
        /// <summary>
        /// lboxCommand 클릭 했을 경우 선택 되어 있는 노드에 있는 폴더와 파일명을 가져와서 Textbox에 보여 줌
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lboxCommand_MouseClick(object sender, MouseEventArgs e)
        {
            if (lboxCommand.SelectedItem == nullreturn;   // 선택 된 아이템이 없을 경우 return
 
            StringBuilder sb = new StringBuilder();
 
            string dirPath = SourcePath();
 
            // Interlock Check (체크가 필요한 구간마다 넣어 주고 이상 시 Log만 호출해서 적어 주면 됨)
            if (string.IsNullOrEmpty(dirPath))
            {
                Log(enLogLevel.Warning, "Source 경로가 입력되어 있지 않습니다.");
                return;
            }
 
            // 해당 Folder 내에 있는 Folder와 File을 가져옴
            if (Directory.Exists(dirPath))
            {
                DirectoryInfo di = new DirectoryInfo(dirPath);
 
                foreach (var directory in di.GetDirectories())
                {
                    sb.Append($"[Folder] {directory} \r\n");
                }
 
                foreach (var file in di.GetFiles())
                {
                    sb.Append($"  {file.Name} \r\n");
                }
 
                tboxFile.Text = sb.ToString();
            }
        }
 
 
        /// <summary>
        /// File 복사 버튼 클릭 시 파일 복사 진행
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCopy_Click(object sender, EventArgs e)
        {
            string sourcePath = SourcePath();    // Source Folder Full Path
            string destinationPath = $@"{tboxDestination.Text}\{DateTime.Now:yyyyMMdd_hhss}";   // File Backup용으로 지정 경로 + 날짜 + 시간 ex) c:\temp\20200410_1033
 
            Log(enLogLevel.Info, $"Source : {sourcePath}");
            Log(enLogLevel.Info, $"Destination : {destinationPath}");
 
            FileSystem.CopyDirectory(sourcePath, destinationPath, UIOption.AllDialogs);
 
            Log(enLogLevel.Info, $"경로 Backup을 완료 하였습니다.");
        }
        #endregion
 
 
 
 
        #region Inner Function
 
        /// <summary>
        /// Folder 경로를 기준으로 Tree View를 새로 그림
        /// </summary>
        /// <param name="treeView">새로 그릴 TreeView Control</param>
        /// <param name="path">Tree View를 그릴 Folder 계층을 가지고 있는 경로</param>
        private void TreeViewLoadbyPath(TreeView treeView, string path)
        {
            // Interlock Check (체크가 필요한 구간마다 넣어 주고 이상 시 Log만 호출해서 적어 주면 됨)
            if (string.IsNullOrEmpty(tboxSource.Text))
            {
                Log(enLogLevel.Warning, "Source 경로가 입력되어 있지 않습니다.");
                return;
            }
 
            treeView.Nodes.Clear();   // 기존의 TreeView를 초기화
 
            DirectoryInfo rootDirectoryInfo = new DirectoryInfo(path);  // DirectoryInfo Class를 선언
            
            treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));  // 
 
            //treeView.Nodes.Add("TEST");   // TreeView에 노드를 추가
            //treeView.Nodes.Remove(treeView.SelectedNode);   // TreeView의 선택 노드를 삭제
        }
 
        /// <summary>
        /// Directory 경로를 TreeNode로 반환
        /// </summary>
        /// <param name="directoryInfo"></param>
        /// <returns></returns>
        private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
        {
            TreeNode directoryNode = new TreeNode(directoryInfo.Name);
 
            //DirectoryInfo[] oTemp = directoryInfo.GetDirectories();   
 
            foreach (var directory in directoryInfo.GetDirectories())   // 해당 경로의 Folder명을 배열로 가져옴
                directoryNode.Nodes.Add(CreateDirectoryNode(directory));   // 경로를 재귀 수로 계속 호출 하면서 하위 노드 들을 찾아 옴
 
            // File 명을 가지고 오기 위한 Node
            //foreach (var file in directoryInfo.GetFiles())
            //    directoryNode.Nodes.Add(new TreeNode(file.Name));
            
            return directoryNode;   // TreeNode에 하위 Node를 반환하고 다시 그 노드를 상위로 반환하고 하는 과정을 반복하면서 트리 구조의 노드를 만들어서 최상위 노드로 보냄
        }
 
        #endregion
 
 
        #region Log OverLoading
        private void Log(enLogLevel eLevel, string LogDesc)
        {
            DateTime dTime = DateTime.Now;
            string LogInfo = $"{dTime:yyyy-MM-dd hh:mm:ss.fff} [{eLevel.ToString()}] {LogDesc}";
            lboxLog.Items.Insert(0, LogInfo);
        }
        private void Log(DateTime dTime, enLogLevel eLevel, string LogDesc)
        {
            string LogInfo = $"{dTime:yyyy-MM-dd hh:mm:ss.fff} [{eLevel.ToString()}] {LogDesc}";
            lboxLog.Items.Insert(0, LogInfo);
        }
 
 
        private string SourcePath()
        {
            string path = tboxSource.Text;
            var lastFolder = Path.GetDirectoryName(path);
            string strpath = lboxCommand.SelectedItem.ToString();   //dc[lboxCommand.SelectedItem.ToString()];
 
            string dirPath = $@"{lastFolder}\{strpath}";  // TextBox에 적어놓은 Local 경로와 TreeNode에서 가져온 하위 경오를 합쳐서 복사 할 폴더가 있는 경로를 만듬
 
            return dirPath;
        }
 
 
 
 
        #endregion
 
        
    }
}
 
cs










댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함