树节点移动操作
----使用微软treeview控件
作者:pfengk
MSN: pfengk@hotmail.com
更多文章请访问:http://www.cnblogs.com/pfengk/
目录
概述................................................................................................................................. 1
操作演示.......................................................................................................................... 1
实现源码:[C#]................................................................................................................ 2
概述
本文集中体现树节点移动实现代码其中很多其他代码省略。如果你对treeview控件不了解,请参阅我的另外一篇文章《web方式下权限分配简单实现》。
源码中引用命名空间Microsoft.Web.UI.WebControls。
本文描述节点移动算法效率非常低下,仅仅适合于节点不多的情况下使用。还请高手们多多指教。联系我的msn,谢谢你们!
操作演示
窗体载入初始界面
选择节点之后
点击[赋予]按钮之后
再次点击[赋予]按钮之后
实现源码:[C#]
1
#region "一棵树到另一棵树的 节点移动方法"
2
3
/// <summary>
4
5
/// 从parentTreeView(森林)的所有根节点中查找childTreeNode是否存在(使用Text属性为关键字比较),存在返回true.
6
7
/// </summary>
8
9
/// <param name="childTreeNode"></param>
10
11
/// <param name="parentTreeNode"></param>
12
13
/// <returns></returns>
14
15
public bool FindNodeFromChildNodes(TreeNode childTreeNode,TreeView parentTreeView)
16
17
{
18
19
bool returnValue = false;
20
21
22
23
foreach(TreeNode tempTreeNode in parentTreeView.Nodes)
24
25
{
26
27
if (childTreeNode.Text == tempTreeNode.Text)
28
29
{
30
31
returnValue = true;
32
33
break;
34
35
}
36
37
}
38
39
return returnValue;
40
41
}
42
43
44
45
/// <summary>
46
47
/// 从parentTreeView(森林)的所有根节点中查找childTreeNode是否存在(使用Text属性为关键字比较),存在返回true.
48
49
/// </summary>
50
51
/// <param name="childTreeNode"></param>
52
53
/// <param name="parentTreeNode"></param>
54
55
/// <returns></returns>
56
57
public bool FindNodeFromChildNodes(TreeNode childTreeNode,TreeView parentTreeView,ref TreeNode foundTreeNode)
58
59
{
60
61
bool returnValue = false;
62
63
64
65
foreach(TreeNode tempTreeNode in parentTreeView.Nodes)
66
67
{
68
69
if (childTreeNode.Text == tempTreeNode.Text)
70
71
{
72
73
returnValue = true;
74
75
foundTreeNode = tempTreeNode;
76
77
break;
78
79
}
80
81
}
82
83
return returnValue;
84
85
}
86
87
88
89
/// <summary>
90
91
/// 从parentTreeNode(根节点)的所有节点中查找childTreeNode是否存在(使用Text属性为关键字比较),存在返回true.
92
93
/// </summary>
94
95
/// <param name="childTreeNode"></param>
96
97
/// <param name="parentTreeNode"></param>
98
99
/// <returns></returns>
100
101
public bool FindNodeFromChildNodes(TreeNode childTreeNode,TreeNode parentTreeNode)
102
103
{
104
105
bool returnValue = false;
106
107
108
109
foreach(TreeNode tempTreeNode in parentTreeNode.Nodes)
110
111
{
112
113
if (childTreeNode.Text == tempTreeNode.Text)
114
115
{
116
117
returnValue = true;
118
119
break;
120
121
}
122
123
}
124
125
return returnValue;
126
127
}
128
129
130
131
/// <summary>
132
133
/// 从parentTreeView(森林)的所有根节点中查找childTreeNode是否存在(使用Text属性为关键字比较),存在返回true.
134
135
/// </summary>
136
137
/// <param name="childTreeNode"></param>
138
139
/// <param name="parentTreeNode"></param>
140
141
/// <returns></returns>
142
143
public bool FindNodeFromChildNodes(TreeNode childTreeNode,TreeNode parentTreeNode,ref TreeNode foundTreeNode)
144
145
{
146
147
bool returnValue = false;
148
149
150
151
foreach(TreeNode tempTreeNode in parentTreeNode.Nodes)
152
153
{
154
155
if (childTreeNode.Text == tempTreeNode.Text)
156
157
{
158
159
returnValue = true;
160
161
foundTreeNode = tempTreeNode;
162
163
break;
164
165
}
166
167
}
168
169
return returnValue;
170
171
}
172
173
174
175
/// <summary>
176
177
/// 移除叶子节点。首先判断是否为叶子节点或根节点,是则移除,否则跳出返回
178
179
/// </summary>
180
181
/// <param name="treeNode"></param>
182
183
/// <returns></returns>
184
185
public bool RemoveLeafageChildNode(ref TreeNode treeNode)
186
187
{
188
189
bool returnValue = false;
190
191
if (treeNode.Nodes == null | treeNode.Nodes.Count == 0)
192
193
{//是子节点时候
194
195
if (treeNode.Parent is TreeNode)
196
197
{//父节点为节点类型时
198
199
int nodesCount = ((TreeNode)treeNode.Parent).Nodes.Count;
200
201
if (nodesCount > 1)
202
203
{//还有兄弟叶子节点时候,仅仅删除本节点
204
205
treeNode.Remove();
206
207
returnValue = true;
208
209
}
210
211
else
212
213
{//是唯一叶子节点时候,还要删除父节点
214
215
//删除本节点
216
217
TreeNode thisParentTreeNode = (TreeNode)treeNode.Parent;
218
219
treeNode.Remove();
220
221
//删除父节点
222
223
returnValue = RemoveLeafageChildNode(ref thisParentTreeNode);
224
225
}
226
227
}
228
229
else
230
231
{//父节点不为节点类型时,他一定是根节点
232
233
treeNode.Remove();
234
235
returnValue = true;
236
237
}
238
239
}
240
241
return returnValue;
242
243
}
244
245
246
247
/// <summary>
248
249
/// 【MoveNodes】将节点分支中所有被选中的节点,移动到另外一个节点分支上。前提根节点必须保留,且各节点Text值唯一。
250
251
/// </summary>
252
253
/// <param name="fromTreeView"></param>
254
255
/// <param name="toTreeNode"></param>
256
257
public void MoveNodes(ref TreeNode fromTreeNode,ref TreeNode toTreeNode)
258
259
{
260
261
bool selected = true;
262
263
//遍历fromTreeNode子节点,比较选中子节点在toTreeNode的子节点集中是否存在,不存在则移动子节点;存在跳过
264
265
int h = fromTreeNode.Nodes.Count-1;
266
267
for (int i = h ; i>=0;i--)
268
269
{
270
271
TreeNode rootNode = new TreeNode();
272
273
rootNode = fromTreeNode.Nodes[i];
274
275
//根节点是否被选中,否则跳过。
276
277
if (rootNode.Checked == selected)
278
279
{
280
281
//本节点是否为叶子节点
282
283
bool isDeleted = false;
284
285
//子节点在 toTreeNode中的子节点集 中是否存在
286
287
if (!FindNodeFromChildNodes (rootNode,toTreeNode))
288
289
{
290
291
//移动节点,判断是否为子节点。是子节点则从fromTreeNode中移除,同时判断是否为唯一节点,是同时移除父节点,
292
293
//反之忽略。
294
295
TreeNode rootNodeClone = ((TreeNode)rootNode.Clone());
296
297
int k = rootNodeClone.Nodes.Count;
298
299
for(int j=0; j<k;j++)
300
301
{
302
303
rootNodeClone.Nodes.RemoveAt(0);
304
305
}
306
307
toTreeNode.Nodes.Add(rootNodeClone);
308
309
310
311
isDeleted = RemoveLeafageChildNode(ref rootNode);
312
313
}
314
315
316
317
//移动子节点的整个分支
318
319
if (!isDeleted)
320
321
{
322
323
TreeNode toRootNode = new TreeNode();
324
325
//定位toTreeNode中与rootNode相同的节点位置。
326
327
FindNodeFromChildNodes(rootNode,toTreeNode,ref toRootNode);
328
329
//移动fromTreeNode中rootNode的分支中所有选中节点到toTreeNode的toRootNode分支中
330
331
MoveNodes(ref rootNode,ref toRootNode);
332
333
}
334
335
}
336
337
}
338
339
}
340
341
/// <summary>
342
343
/// 【MoveNodes】将一棵树中所有被选中的节点,移动到另外一棵树上。前提根节点必须保留,且各节点Text值唯一。
344
345
/// </summary>
346
347
/// <param name="fromTreeNode"></param>
348
349
/// <param name="toTreeNode"></param>
350
351
public void MoveNodes(ref TreeView fromTreeView,ref TreeView toTreeView)
352
353
{
354
355
bool selected = true;
356
357
358
359
//遍历fromTreeView根节点,比较选中节点在toTreeView的根节点集中是否存在,不存在则移动节点;存在跳过
360
361
362
363
int h = fromTreeView.Nodes.Count-1;
364
365
for (int i = h ; i>=0;i--)
366
367
{
368
369
TreeNode rootNode = new TreeNode();
370
371
rootNode = fromTreeView.Nodes[i];
372
373
//根节点是否被选中,否则跳过。
374
375
if (rootNode.Checked == selected)
376
377
{
378
379
//本节点是否为叶子节点
380
381
bool isDeleted = false;
382
383
//根节点在 toTreeView中的根节点中是否存在
384
385
if (!FindNodeFromChildNodes (rootNode,toTreeView))
386
387
{
388
389
//移动节点,判断是否为子节点。是子节点则从fromTreeView中移除,同时判断是否为唯一节点,是同时移除父节点,
390
391
//反之忽略。
392
393
TreeNode rootNodeClone = ((TreeNode)rootNode.Clone());
394
395
int k = rootNodeClone.Nodes.Count;
396
397
for(int j=0; j<k;j++)
398
399
{
400
401
rootNodeClone.Nodes.RemoveAt(0);
402
403
}
404
405
406
407
toTreeView.Nodes.Add(rootNodeClone);
408
409
410
411
isDeleted = RemoveLeafageChildNode(ref rootNode);
412
413
}
414
415
//移动根节点的整个分支
416
417
if (!isDeleted)
418
419
{
420
421
TreeNode toRootNode = new TreeNode();
422
423
//定位toTreeView中与rootNode相同的节点位置。
424
425
FindNodeFromChildNodes(rootNode,toTreeView,ref toRootNode);
426
427
//移动fromTreeView中rootNode的分支中所有选中节点到toTreeView的toRootNode分支中
428
429
MoveNodes(ref rootNode,ref toRootNode);
430
431
}
432
433
}
434
435
}
436
437
}
438
439
440
441
#endregion
442
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
[THE END]
搜索一下相关内容 |