
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
6
using System.Collections;
7
using System.ComponentModel;
8
using System.Data;
9
using System.Diagnostics;
10
using System.Drawing;//Point
11
using System.Windows.Forms;//TreeNode
12
13
14
namespace upLibrary.upControls
15

{
16
/**//// <summary>
17
/// 实现了拖放操作处理,并且每一个结点的添加和移除都能引发事件的TreeView。
18
/// </summary>
19
20
public class upTreeViewBase : System.Windows.Forms.TreeView
21
{
22
private System.ComponentModel.Container components = null;
23
private TreeNode _DragNode;
24
private bool _MoveNode = false;
25
private bool _CopyNode = false;
26
//private bool _CanDropDrag = false;
27
28
/**//// <summary>
29
/// 删除节点事件句柄(sender 是父结点或为空,e.Node是子结点)
30
/// </summary>
31
32
public delegate void NodeDeleteHandler(object Sender, upLibrary.upControls.TreeNodeEventArgs e);
33
34
/**//// <summary>
35
/// 增加节点事件句柄(sender 是父结点或为空,e.Node是子结点)
36
/// </summary>
37
38
public delegate void NodeAddHandler(object Sender, upLibrary.upControls.TreeNodeEventArgs e);
39
40
/**//// <summary>
41
/// 在删除或增加节点之间浏览子节点事件句柄(sender 是父结点或为空,e.Node是子结点)
42
/// </summary>
43
44
public delegate void BrowseTreeNodesEventHandler(object Sender, TreeNodeEventArgs e);
45
46
/**//// <summary>
47
/// 在拖放操作中改变父结点事件句柄(sender 是父结点或为空,e.Node是子结点)
48
/// </summary>
49
50
public delegate void ParentChangByDrapDropHandler(object Sender, TreeNodeEventArgs e);
51
52
控件事件声明#region 控件事件声明
53
54
[Description("在拖放操作中改变结点的父之前发生此事件")]
55
56
public event ParentChangByDrapDropHandler ParentChangingByDrapDrop;
57
58
[Description("在拖放操作中改变了结点的父之后发生此事件")]
59
60
public event ParentChangByDrapDropHandler ParentChangedByDrapDrop;
61
62
[Description("sender所代表的节点将被移除,通常在移动拖放操作之前后发生,或树已加载后再移除之前发生")]
63
64
public event NodeDeleteHandler NodeDeleting;
65
66
[Description("sender所代表的节点将被添加,通常在移动或复制拖放操作完成后发生,或树已加载后再新增之前发生")]
67
68
public event NodeAddHandler NodeAdding;
69
70
[Description("sender所代表的节点被移除,通常在移动拖放操作完成后发生,或树已加载后再移除节点后发生")]
71
72
public event NodeDeleteHandler NodeDeleted;
73
74
[Description("sender所代表的节点被添加,通常在移动或复制拖放操作完成后发生,或树已加载后再新增节点后发生")]
75
76
public event NodeAddHandler NodeAdded;
77
78
[Description("当调用BrowseNodes时从最低层开始遍历到指定node时发生此事件")]
79
80
public event BrowseTreeNodesEventHandler InverseBrowseTreeNodes;
81
82
[Description("向下遍历到指定node时发生此事件")]
83
84
public event BrowseTreeNodesEventHandler DownBrowseTreeNodes;
85
86
#endregion
87
88
public upTreeViewBase()
89
{
90
InitializeComponent();
91
}
92
93
组件设计器生成的代码#region 组件设计器生成的代码
94
95
/**//// <summary>
96
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
97
/// 此方法的内容。
98
/// </summary>
99
100
private void InitializeComponent()
101
{
102
components = new System.ComponentModel.Container();
103
}
104
105
#endregion
106
107
"拖放相关"#region "拖放相关"
108
109
/**//// <summary>
110
/// 是否移动型拖放
111
/// </summary>
112
113
public bool CanMoveNode
114
{
115
get
{ return _MoveNode; }
116
set
117
{
118
this.ItemDrag -= new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
119
this.DragEnter -= new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
120
this.DragDrop -= new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
121
_MoveNode = value;
122
if (_MoveNode)
123
{
124
this.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
125
this.DragEnter += new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
126
this.DragDrop += new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
127
}
128
}
129
}
130
131
/**//// <summary>
132
/// 是否复制型拖放
133
/// </summary>
134
135
public bool CanCopyNode
136
{
137
get
{ return _CopyNode; }
138
set
139
{
140
this.ItemDrag -= new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
141
this.DragEnter -= new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
142
this.DragDrop -= new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
143
_CopyNode = value;
144
if (_CopyNode)
145
{
146
this.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
147
this.DragEnter += new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
148
this.DragDrop += new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
149
}
150
}
151
}
152
153
/**//// <summary>
154
/// 开始拖放
155
/// </summary>
156
/// <param name="sender"></param>
157
/// <param name="e"></param>
158
159
protected void TreeView_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
160
{
161
this._DragNode = (TreeNode)e.Item;
162
string strItem = e.Item.ToString();
163
if (_CopyNode && _MoveNode)
164
DoDragDrop(strItem, DragDropEffects.Move | DragDropEffects.Copy);
165
else if (_CopyNode)
166
DoDragDrop(strItem, DragDropEffects.Copy);
167
else if (_MoveNode)
168
DoDragDrop(strItem, DragDropEffects.Move);
169
}
170
171
/**//// <summary>
172
/// 拖入到控件边界内时
173
/// </summary>
174
/// <param name="sender"></param>
175
/// <param name="e"></param>
176
177
protected void TreeView_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
178
{
179
if (e.Data.GetDataPresent(DataFormats.Text))
180
{
181
if ((e.KeyState & 4) == 4 && (e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
182
e.Effect = DragDropEffects.Move; // SHIFT KeyState for move.
183
else if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
184
e.Effect = DragDropEffects.Copy; // CTRL KeyState for copy.
185
else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
186
e.Effect = DragDropEffects.Move; // By default, the drop action should be move, if allowed.
187
else
188
e.Effect = DragDropEffects.None;
189
}
190
else
191
e.Effect = DragDropEffects.None;
192
}
193
194
/**//// <summary>
195
/// 拖放完成
196
/// </summary>
197
/// <param name="sender"></param>
198
/// <param name="e"></param>
199
200
protected void TreeView_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
201
{
202
upLibrary.upControls.TreeNodeEventArgs args = null;
203
bool cancel = false;
204
Point Position = new Point(e.X, e.Y);
205
Position = this.PointToClient(Position);
206
TreeNode DropNode = this.GetNodeAt(Position); //承载结点
207
if (_DragNode.Parent == DropNode) return; //没有变嘛
208
TreeNode oldparent = _DragNode.Parent;
209
210
if ((e.Effect & DragDropEffects.Move) == DragDropEffects.Move) //如果是移动型就只是改一下父结点
211
{
212
if (ParentChangingByDrapDrop != null)
213
{
214
args = new upLibrary.upControls.TreeNodeEventArgs(_DragNode, oldparent, DropNode, TreeNodeOperateType.Modify, ref cancel);
215
ParentChangingByDrapDrop(this, args);
216
if (args.Cancel == true) return;
217
}
218
_DragNode.Remove();
219
220
if (DropNode != null)
221
DropNode.Nodes.Add(_DragNode); //如果树节点位于根级别,Parent 属性即为空引用
222
else
223
this.Nodes.Add(_DragNode);
224
225
if (ParentChangedByDrapDrop != null)
226
{
227
args = new upLibrary.upControls.TreeNodeEventArgs(_DragNode, oldparent, DropNode, TreeNodeOperateType.Modify, ref cancel);
228
ParentChangedByDrapDrop(this, args);
229
}
230
}
231
else //否则是复制型的话则要在承载结点处新增结点
232
{
233
TreeNode tNode = (TreeNode)_DragNode.Clone(); //是复制型的当然要新做一个啦,复制的部分包括克隆的树节点及其以下的树结构
234
this.AddNode(DropNode, tNode); //tNode及其子node都会在事件中去加入
235
}
236
}
237
238
#endregion
239
240
"增加和移除Node并引发事件"#region "增加和移除Node并引发事件"
241
242
/**//// <summary>
243
/// 加一个新Node至指定的上级Node
244
/// </summary>
245
/// <param name="newParent"></param>
246
/// <param name="nodeText"></param>
247
/// <returns>表示成功与否</returns>
248
249
public bool AddNode(TreeNode newParent, string nodeText)
250
{
251
return AddNode(newParent, new TreeNode(nodeText));
252
}
253
254
/**//// <summary>
255
/// 加一个Node至指定的上级Node
256
/// </summary>
257
/// <param name="newParent"></param>
258
/// <param name="node"></param>
259
/// <returns>表示成功与否</returns>
260
261
public bool AddNode(TreeNode newParent,TreeNode node)
262
{
263
bool cancel = false;
264
if (node != null)
265
{
266
this.DownBrowseTreeNodes += new BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByAdd);
267
TreeNodeEventArgs args = new TreeNodeEventArgs(node, node.Parent, newParent, TreeNodeOperateType.AddNew, ref cancel);
268
this.OnAdownBrowseTreeNodes(args); //让在事件中去一级级地处理
269
this.DownBrowseTreeNodes -= new BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByAdd);
270
}
271
return !cancel;
272
}
273
274
private void upTreeViewBase_BrowseTreeNodesByAdd(object Sender, TreeNodeEventArgs e)
275
{
276
if (e.OperateType == TreeNodeOperateType.AddNew)
277
{
278
if (this.NodeAdding != null)
279
{
280
NodeAdding(this, e);
281
if (e.Cancel) return;
282
}
283
e.Node.Remove();
284
if (e.NewParent != null)
285
e.NewParent.Nodes.Add(e.Node);
286
else
287
this.Nodes.Add(e.Node);
288
if (this.NodeAdded != null)
289
NodeAdded(this, e);
290
}
291
}
292
293
/**//// <summary>
294
/// 删除用户选定的当前Node
295
/// </summary>
296
/// <returns>表示成功与否</returns>
297
298
public bool DeleteNode()
299
{
300
TreeNode node = this.SelectedNode;
301
if (node != null)
302
{
303
return DeleteNode(node);
304
}
305
return false;
306
}
307
308
/**//// <summary>
309
/// 删除参数指定的Node及其子Node,从最低层开始,并在删除Node之前后分别引发事件NodeDeleting 和 NodeDeleted
310
/// </summary>
311
/// <param name="node"></param>
312
/// <returns>表示成功与否</returns>
313
314
public bool DeleteNode(TreeNode node)
315
{
316
bool cancel = false;
317
if (node != null)
318
{
319
this.InverseBrowseTreeNodes += new BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByDelete);
320
TreeNodeEventArgs args = new TreeNodeEventArgs(node, node.Parent, null, TreeNodeOperateType.Delete, ref cancel);
321
this.OnInverseBrowseTreeNodes(args); //让在事件中去一级级地处理
322
this.InverseBrowseTreeNodes -= new BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByDelete);
323
}
324
return !cancel;
325
}
326
327
private void upTreeViewBase_BrowseTreeNodesByDelete(object Sender, TreeNodeEventArgs e)
328
{
329
if (e.OperateType == TreeNodeOperateType.Delete)
330
{
331
if (this.NodeDeleting != null)
332
{
333
NodeDeleting(this, e);
334
if (e.Cancel) return;
335
}
336
e.Node.Remove();
337
if (this.NodeDeleted != null)
338
NodeDeleted(this, e);
339
}
340
}
341
342
#endregion
343
344
遍历并引发事件#region 遍历并引发事件
345
346
/**//// <summary>
347
/// 逆向遍历参数NODEX代表的节点及其所有子节点,从最底层起一层一层地引发BrowseChildNode事件
348
/// </summary>
349
350
protected void OnInverseBrowseTreeNodes(TreeNodeEventArgs args)
351
{
352
bool cancel = false;
353
TreeNode ChildNode = null, BrotherNode = null;
354
TreeNode Nodex = args.Node;
355
if (Nodex == null) return;
356
357
if (Nodex.Nodes.Count > 0)
358
{
359
ChildNode = Nodex.Nodes[0]; //能执行到此,表示有子节点
360
while (ChildNode != null && !args.Cancel) //兄弟节点可能有多个
361
{
362
BrotherNode = ChildNode.NextNode;
363
TreeNodeEventArgs arg = new TreeNodeEventArgs(ChildNode, ChildNode.Parent, ChildNode.Parent, args.OperateType, ref cancel);
364
OnInverseBrowseTreeNodes(arg);
365
args.Cancel = arg.Cancel;
366
if (arg.Cancel) return;
367
ChildNode = BrotherNode;
368
}
369
}
370
371
if (!args.Cancel) //如果下一级的事件中指定了取消,就不引发本级的事件了
372
{
373
if (InverseBrowseTreeNodes != null)
374
InverseBrowseTreeNodes(this, args); //当没有子节点时,该节点就是末节,在事件中去处理吧,
375
}
376
}
377
378
/**//// <summary>
379
/// 正向遍历参数NODEX代表的节点及其所有子节点,在事件中的操作不可逆,Cancel为真只能停止遍历
380
/// </summary>
381
382
protected void OnAdownBrowseTreeNodes(TreeNodeEventArgs args)
383
{
384
bool cancel = false;
385
TreeNode ChildNode = null, BrotherNode = null;
386
TreeNode Nodex = args.Node;
387
388
if (Nodex != null)
389
{
390
if (DownBrowseTreeNodes != null)
391
DownBrowseTreeNodes(this, args); //首先处理自己
392
if (args.Cancel) return; //要求取消,不用管下一级了
393
if (Nodex.Nodes.Count <= 0) return; //根本就没有下一级了
394
395
ChildNode = Nodex.Nodes[0]; //能执行到此,表示有子节点
396
while (ChildNode != null && !args.Cancel) //兄弟节点可能有多个
397
{
398
BrotherNode = ChildNode.NextNode;
399
TreeNodeEventArgs arg = new TreeNodeEventArgs(ChildNode, ChildNode.Parent, ChildNode.Parent, args.OperateType, ref cancel);
400
OnAdownBrowseTreeNodes(arg);
401
args.Cancel = arg.Cancel;
402
if (arg.Cancel) return;
403
ChildNode = BrotherNode;
404
}
405
}
406
}
407
408
#endregion
409
}
410
411
/**//// <summary>
412
/// 遍历指定的node及其子node时的操作类型
413
/// </summary>
414
415
public enum TreeNodeOperateType
416
{
417
BrowseOnly = 1, AddNew, Modify, Delete
418
}
419
420
public class TreeNodeEventArgs : System.EventArgs
421
{
422
private TreeNode _Node, _OldParent, _NewParent;
423
private bool _Cancel;
424
private TreeNodeOperateType _OperateType;
425
426
/**//// <summary>
427
/// 使用此事件数据时,Sender 应是Node的Parent
428
/// </summary>
429
/// <param name="Node">要加入到Sender所代表的Nodes的Node</param>
430
/// <param name="OperateType">发起遍历的操作类型</param>
431
/// <param name="Cancel">在事件处理中是否要求出污</param>
432
433
public TreeNodeEventArgs(TreeNode Node, TreeNode oldParent, TreeNode newParent, TreeNodeOperateType OperateType, ref bool Cancel)
434
: base()
435
{
436
437
_OldParent = oldParent;
438
439
_NewParent = newParent;
440
441
_Node = Node;
442
443
_Cancel = Cancel;
444
445
_OperateType = OperateType;
446
447
}
448
449
public TreeNode OldParent
450
{
451
452
get
{ return _OldParent; }
453
454
set
{ _OldParent = value; }
455
456
}
457
458
public TreeNode NewParent
459
{
460
461
get
{ return _NewParent; }
462
463
set
{ _NewParent = value; }
464
465
}
466
467
public TreeNode Node
468
{
469
470
get
{ return _Node; }
471
472
set
{ _Node = value; }
473
474
}
475
476
public TreeNodeOperateType OperateType
477
{
478
479
get
{ return _OperateType; }
480
481
set
{ _OperateType = value; }
482
483
}
484
485
public bool Cancel
486
{
487
488
get
489
{
490
491
return _Cancel;
492
493
}
494
495
set
496
{
497
498
_Cancel = value;
499
500
}
501
502
}
503
504
}
505
506
}
507
转载于:https://www.cnblogs.com/Jackey_Chen/archive/2008/10/30/1323241.html