实现了拖放操作处理,并且每一个结点的添加和移除都能引发事件的TreeView

类别:.NET开发 点击:0 评论:0 推荐:


///如未特别说明,本人所发表的技术文章都为原创, 任何人引用都请注明出处,并包含本声明
///作者: CSDN网名alias88,邮件:[email protected],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;

      }

    }

 

  }

}

 

 

 

 

 

本文地址:http://com.8s8s.com/it/it42168.htm