///如未特别说明,本人所发表的技术文章都为原创, 任何人引用都请注明出处,并包含本声明
///作者: CSDN网名alias88,邮件:alias88@163.com,QQ:63343
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
namespace upLibrary.upControls
{
/// <summary>
/// 实现了拖放操作处理,并且每一个结点的添加和移除都能引发事件的TreeView。
/// </summary>
public class upTreeViewBase : System.Windows.Forms.TreeView
{
private System.ComponentModel.Container components = null;
private TreeNode _DragNode;
private bool _MoveNode=false;
private bool _CopyNode=false;
private bool _CanDropDrag=false;
/// <summary>
/// 删除节点事件句柄(sender 是父结点或为空,e.Node是子结点)
/// </summary>
public delegate void NodeDeleteHandler (object Sender,upLibrary.upControls.TreeNodeEventArgs e);
/// <summary>
/// 增加节点事件句柄(sender 是父结点或为空,e.Node是子结点)
/// </summary>
public delegate void NodeAddHandler (object Sender,upLibrary.upControls.TreeNodeEventArgs e);
/// <summary>
/// 在删除或增加节点之间浏览子节点事件句柄(sender 是父结点或为空,e.Node是子结点)
/// </summary>
public delegate void
BrowseTreeNodesEventHandler (object Sender,TreeNodeEventArgs e);
/// <summary>
/// 在拖放操作中改变父结点事件句柄(sender 是父结点或为空,e.Node是子结点)
/// </summary>
public delegate void ParentChangByDrapDropHandler (object Sender,TreeNodeEventArgs e);
[Description("在拖放操作中改变结点的父之前发生此事件") ]
public event ParentChangByDrapDropHandler ParentChangingByDrapDrop;
[Description("在拖放操作中改变了结点的父之后发生此事件") ]
public event ParentChangByDrapDropHandler ParentChangedByDrapDrop;
[Description("sender所代表的节点将被移除,通常在移动拖放操作之前后发生,或树已加载后再移除之前发生") ]
public event NodeDeleteHandler NodeDeleting;
[Description("sender所代表的节点将被添加,通常在移动或复制拖放操作完成后发生,或树已加载后再新增之前发生") ]
public event NodeAddHandler NodeAdding;
[Description("sender所代表的节点被移除,通常在移动拖放操作完成后发生,或树已加载后再移除节点后发生") ]
public event NodeDeleteHandler NodeDeleted;
[Description("sender所代表的节点被添加,通常在移动或复制拖放操作完成后发生,或树已加载后再新增节点后发生") ]
public event NodeAddHandler NodeAdded;
[Description("当调用BrowseNodes时从最低层开始遍历到指定node时发生此事件") ]
public event
BrowseTreeNodesEventHandler InverseBrowseTreeNodes;
[Description("向下遍历到指定node时发生此事件") ]
public event
BrowseTreeNodesEventHandler DownBrowseTreeNodes;
public upTreeViewBase()
{
InitializeComponent();
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
#region "拖放相关"
/// <summary>
/// 是否移动型拖放
/// </summary>
public bool CanMoveNode
{
get{return _MoveNode;}
set
{
this.ItemDrag -= new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
this.DragEnter -= new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
this.DragDrop -= new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
_MoveNode=value;
if (_MoveNode)
{
this.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
this.DragEnter += new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
this.DragDrop += new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
}
}
}
/// <summary>
/// 是否复制型拖放
/// </summary>
public bool CanCopyNode
{
get{return _CopyNode;}
set
{
this.ItemDrag -= new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
this.DragEnter -= new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
this.DragDrop -= new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
_CopyNode=value;
if (_CopyNode)
{
this.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(TreeView_ItemDrag);
this.DragEnter += new System.Windows.Forms.DragEventHandler(TreeView_DragEnter);
this.DragDrop += new System.Windows.Forms.DragEventHandler(TreeView_DragDrop);
}
}
}
/// <summary>
/// 开始拖放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void TreeView_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
{
this._DragNode = (TreeNode)e.Item;
string strItem = e.Item.ToString();
if (_CopyNode && _MoveNode)
DoDragDrop(strItem, DragDropEffects.Move | DragDropEffects.Copy );
else if (_CopyNode)
DoDragDrop(strItem, DragDropEffects.Copy );
else if (_MoveNode)
DoDragDrop(strItem, DragDropEffects.Move );
}
/// <summary>
/// 拖入到控件边界内时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void TreeView_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Text))
{
if ((e.KeyState & 4) == 4 && (e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
e.Effect = DragDropEffects.Move; // SHIFT KeyState for move.
else if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
e.Effect = DragDropEffects.Copy; // CTRL KeyState for copy.
else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
e.Effect = DragDropEffects.Move; // By default, the drop action should be move, if allowed.
else
e.Effect = DragDropEffects.None;
}
else
e.Effect = DragDropEffects.None;
}
/// <summary>
/// 拖放完成
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void TreeView_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
upLibrary.upControls.TreeNodeEventArgs args=null;
bool cancel=false;
Point Position = new Point(e.X ,e.Y );
Position = this.PointToClient(Position);
TreeNode DropNode = this.GetNodeAt(Position); //承载结点
if (_DragNode.Parent == DropNode) return ; //没有变嘛
TreeNode oldparent=_DragNode.Parent ;
if ((e.Effect & DragDropEffects.Move) ==DragDropEffects.Move ) //如果是移动型就只是改一下父结点
{
if (ParentChangingByDrapDrop !=null)
{
args=new upLibrary.upControls.TreeNodeEventArgs(_DragNode,oldparent ,DropNode,TreeNodeOperateType.Modify ,ref cancel);
ParentChangingByDrapDrop(this ,args);
if (args.Cancel ==true) return ;
}
_DragNode.Remove();
if (DropNode!=null)
DropNode.Nodes .Add (_DragNode); //如果树节点位于根级别,Parent 属性即为空引用
else
this.Nodes.Add (_DragNode);
if (ParentChangedByDrapDrop!=null)
{
args=new upLibrary.upControls.TreeNodeEventArgs(_DragNode,oldparent ,DropNode,TreeNodeOperateType.Modify ,ref cancel);
ParentChangedByDrapDrop(this,args);
}
}
else //否则是复制型的话则要在承载结点处新增结点
{
TreeNode tNode=(TreeNode)_DragNode.Clone (); //是复制型的当然要新做一个啦,复制的部分包括克隆的树节点及其以下的树结构
this.AddNode (DropNode,tNode); //tNode及其子node都会在事件中去加入
}
}
#endregion
#region "增加和移除Node并引发事件"
/// <summary>
/// 加一个新Node至指定的上级Node
/// </summary>
/// <param name="newParent"></param>
/// <param name="nodeText"></param>
/// <returns>表示成功与否</returns>
public bool AddNode(TreeNode newParent,string nodeText)
{
return AddNode(newParent,new TreeNode (nodeText));
}
/// <summary>
/// 加一个Node至指定的上级Node
/// </summary>
/// <param name="newParent"></param>
/// <param name="node"></param>
/// <returns>表示成功与否</returns>
public bool AddNode(TreeNode newParent,TreeNode node)
{
bool cancel=false;
if (node!=null)
{
this.DownBrowseTreeNodes +=new
BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByAdd);
TreeNodeEventArgs args=new TreeNodeEventArgs (node,node.Parent ,newParent,TreeNodeOperateType.AddNew ,ref cancel);
this.OnAdownBrowseTreeNodes (args); //让在事件中去一级级地处理
this.DownBrowseTreeNodes -=new
BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByAdd);
}
return !cancel ;
}
private void upTreeViewBase_BrowseTreeNodesByAdd(object Sender, TreeNodeEventArgs e)
{
if (e.OperateType ==TreeNodeOperateType.AddNew )
{
if (this.NodeAdding !=null)
{
NodeAdding(this ,e);
if (e.Cancel ) return ;
}
e.Node.Remove ();
if (e.NewParent !=null)
e.NewParent.Nodes.Add (e.Node );
else
this.Nodes.Add (e.Node );
if(this.NodeAdded !=null)
NodeAdded(this ,e);
}
}
/// <summary>
/// 删除用户选定的当前Node
/// </summary>
/// <returns>表示成功与否</returns>
public bool DeleteNode()
{
TreeNode node=this.SelectedNode ;
if (node!=null)
{
return DeleteNode(node);
}
return false;
}
/// <summary>
/// 删除参数指定的Node及其子Node,从最低层开始,并在删除Node之前后分别引发事件NodeDeleting 和 NodeDeleted
/// </summary>
/// <param name="node"></param>
/// <returns>表示成功与否</returns>
public bool DeleteNode(TreeNode node)
{
bool cancel=false;
if (node!=null)
{
this.InverseBrowseTreeNodes +=new
BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByDelete);
TreeNodeEventArgs args=new TreeNodeEventArgs (node,node.Parent ,null,TreeNodeOperateType.Delete ,ref cancel);
this.OnInverseBrowseTreeNodes (args ); //让在事件中去一级级地处理
this.InverseBrowseTreeNodes -=new
BrowseTreeNodesEventHandler(upTreeViewBase_BrowseTreeNodesByDelete);
}
return !cancel ;
}
private void upTreeViewBase_BrowseTreeNodesByDelete(object Sender, TreeNodeEventArgs e)
{
if (e.OperateType ==TreeNodeOperateType.Delete )
{
if (this.NodeDeleting !=null)
{
NodeDeleting(this ,e);
if (e.Cancel ) return ;
}
e.Node.Remove ();
if(this.NodeDeleted !=null)
NodeDeleted(this ,e);
}
}
#endregion
#region 遍历并引发事件
/// <summary>
/// 逆向遍历参数NODEX代表的节点及其所有子节点,从最底层起一层一层地引发BrowseChildNode事件
/// </summary>
protected void OnInverseBrowseTreeNodes(TreeNodeEventArgs args)
{
bool cancel=false;
TreeNode ChildNode=null,BrotherNode=null;
TreeNode Nodex=args.Node ;
if (Nodex==null ) return ;
if ( Nodex.Nodes.Count >0 )
{
ChildNode=Nodex.Nodes[0] ; //能执行到此,表示有子节点
while (ChildNode!=null && !args.Cancel ) //兄弟节点可能有多个
{
BrotherNode=ChildNode.NextNode;
TreeNodeEventArgs arg=new TreeNodeEventArgs (ChildNode,ChildNode.Parent ,ChildNode.Parent ,args.OperateType ,ref cancel);
OnInverseBrowseTreeNodes(arg);
args.Cancel =arg.Cancel ;
if (arg.Cancel ) return ;
ChildNode=BrotherNode;
}
}
if (!args.Cancel ) //如果下一级的事件中指定了取消,就不引发本级的事件了
{
if(InverseBrowseTreeNodes!=null)
InverseBrowseTreeNodes (this,args); //当没有子节点时,该节点就是末节,在事件中去处理吧,
}
}
/// <summary>
/// 正向遍历参数NODEX代表的节点及其所有子节点,在事件中的操作不可逆,Cancel为真只能停止遍历
/// </summary>
protected void OnAdownBrowseTreeNodes(TreeNodeEventArgs args)
{
bool cancel=false;
TreeNode ChildNode=null,BrotherNode=null;
TreeNode Nodex =args.Node ;
if (Nodex!=null)
{
if(DownBrowseTreeNodes!=null)
DownBrowseTreeNodes (this ,args); //首先处理自己
if (args.Cancel ) return ; //要求取消,不用管下一级了
if (Nodex.Nodes.Count<=0) return ; //根本就没有下一级了
ChildNode=Nodex.Nodes[0] ; //能执行到此,表示有子节点
while (ChildNode!=null && !args.Cancel) //兄弟节点可能有多个
{
BrotherNode=ChildNode.NextNode;
TreeNodeEventArgs arg=new TreeNodeEventArgs (ChildNode,ChildNode.Parent ,ChildNode.Parent ,args.OperateType ,ref cancel);
OnAdownBrowseTreeNodes(arg);
args.Cancel =arg.Cancel ;
if (arg.Cancel ) return ;
ChildNode=BrotherNode;
}
}
}
#endregion
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// 遍历指定的node及其子node时的操作类型
/// </summary>
public enum TreeNodeOperateType
{
BrowseOnly=1,AddNew,Modify,Delete
}
public class TreeNodeEventArgs:System.EventArgs
{
private TreeNode _Node,_OldParent,_NewParent;
private bool _Cancel;
private TreeNodeOperateType _OperateType;
/// <summary>
/// 使用此事件数据时,Sender 应是Node的Parent
/// </summary>
/// <param name="Node">要加入到Sender所代表的Nodes的Node</param>
/// <param name="OperateType">发起遍历的操作类型</param>
/// <param name="Cancel">在事件处理中是否要求出污</param>
public TreeNodeEventArgs(TreeNode Node ,TreeNode oldParent,TreeNode newParent,TreeNodeOperateType OperateType, ref bool Cancel ):base()
{
_OldParent=oldParent;
_NewParent=newParent;
_Node=Node;
_Cancel=Cancel;
_OperateType=OperateType;
}
public TreeNode OldParent
{
get { return _OldParent; }
set { _OldParent = value; }
}
public TreeNode NewParent
{
get { return _NewParent; }
set { _NewParent = value; }
}
public TreeNode Node
{
get { return _Node; }
set { _Node = value; }
}
public TreeNodeOperateType OperateType
{
get { return _OperateType;}
set { _OperateType=value; }
}
public bool Cancel
{
get {
return _Cancel;
}
set {
_Cancel = value;
}
}
}
}