当前位置:编程学习 > C#/ASP.NET >>

TreeView的撤销操作问题?


  在进行TreeView节点移动的时候,如果用户不小心移动错误,那么该如何设置一个

按钮来允许用户进行撤销操作啊。怎么才能实现撤销啊?真是麻烦啊!谢谢大侠啦!

^-^ --------------------编程问答-------------------- 沙发,帮忙顶 --------------------编程问答-------------------- MIDAS --------------------编程问答-------------------- 设置一个类用来保存要移动的节点的位置以及数据,撤消时再添加回去。 --------------------编程问答-------------------- 节点还要绑定数据,数据也要变回原来的 --------------------编程问答-------------------- 哪位大好人帮忙给写一下啊? --------------------编程问答-------------------- 不会,帮顶! --------------------编程问答-------------------- mark 帮顶 --------------------编程问答-------------------- treeview类没有你要的现成的功能函数,需要你自己写一个这样的函数。每一步操作都保存记录(可以是多个便于恢复多步),一旦需要就调用这个函数,每操作一步,更新保存的信息。这样就行了,以前做个!
--------------------编程问答-------------------- gisfarmer(菜菜阿杰) 以前做过能不能给个例子啊?我的邮箱shidongye123456@163.com --------------------编程问答-------------------- 不好意思!找了半天,也没有找到。不难,以前我是用VC写的。
--------------------编程问答-------------------- 哦,不过我自己写可真的是费劲啊。真是郁闷!唉,不过谢谢你啦^-^ --------------------编程问答-------------------- 帮顶 --------------------编程问答-------------------- 等我写完就散分,放心吧,不会很久地!也就十天半月的吧!^-^ --------------------编程问答-------------------- 我会耐心的等
 zhaowen6666678() ( ) 信誉:100  2007-08-20 15:08:26  得分: 0  
 
 
   等我写完就散分,放心吧,不会很久地!也就十天半月的吧!^-^
  
 
--------------------编程问答-------------------- 呵呵....马上快有结果啦!嘿嘿.... --------------------编程问答-------------------- 不知道还有没有人关注
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace UndoTreeView
{
    public partial class Form1 : Form
    {

        int CtrlMask = 8;
        ArrayList nDestNote = new ArrayList();
        ArrayList nSource = new ArrayList();


        public Form1()
        {
            InitializeComponent();
        }

        private void button3_Click(object sender, EventArgs e)
        {
             Undo();                
        }

        private void treeView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                //DoDragDrop 方法确定当前光标位置下的控件。然后它将检查该控件是否是有效的放置目标。
                DoDragDrop(e.Item, DragDropEffects.Move | DragDropEffects.Copy);

            }
        }

        private void treeView_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode"))
            {

                if ((e.KeyState & CtrlMask) == CtrlMask)
                {
                    e.Effect = DragDropEffects.Copy;
                }
                else
                {
                    //MessageBox.Show("该节点将被删除!");
                    e.Effect = DragDropEffects.Move;
                }
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void treeView_DragDrop(object sender, DragEventArgs e)
        {
            TreeNode OriginationNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode"); //(TreeNode)OriginationNode.Clone()

            if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
            {
                Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
                TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);
                
                if (((TreeNode)OriginationNode).Index - 1 >= 0)
                {
                    nSource.Add(((TreeNode)OriginationNode).Parent.Nodes[((TreeNode)OriginationNode).Index - 1]);
                }
                else 
                {
                    MessageBox.Show("你移动的是Index为0的节点!");
                }
                

                if (IfMove(DestinationNode, (TreeNode)OriginationNode))
                {
                    if (DestinationNode.Parent == ((TreeNode)OriginationNode).Parent)    //DestinationNode.Name.Length == ((TreeNode)OriginationNode).Name.Length && (TreeNode)OriginationNode.Parent!=null
                    {

                        DestinationNode.Parent.Nodes.Insert(DestinationNode.Index + 1, (TreeNode)OriginationNode.Clone());
                        //DestinationNode.Expand();

                        if ((e.KeyState & CtrlMask) != CtrlMask)
                        {
                            OriginationNode.Remove();
                        }

                        nDestNote.Add(DestinationNode.Parent.Nodes[DestinationNode.Index+1]);

                    }
                    else
                    {
                        DestinationNode.Parent.Nodes.Insert(DestinationNode.Index + 1, (TreeNode)OriginationNode.Clone());
                        //DestinationNode.Expand();

                        if ((e.KeyState & CtrlMask) != CtrlMask)
                        {
                            OriginationNode.Remove();
                        }

                        nDestNote.Add(DestinationNode.Parent.Nodes[DestinationNode.Index + 1]);
                        //MessageBox.Show("不是平级移动!");
                    }
                }

            }

            i = nDestNote.Count; 
        }

        //判断nDest是否在nSource内部,是则不允许移动
        private bool IfMove(TreeNode nDest, TreeNode nSource)
        {
            if (nDest.Parent != nSource && nDest.Parent != null)
            {
                IfMove(nDest.Parent, nSource); //一直比到nDest.Parent = null为止
            }
            else if (nDest.Parent == null)
            {
                return true;
            }
            else if (nDest.Parent == nSource)
            {
                return false;
            }

            return IfMove(nDest.Parent, nSource);
        }

        //创建撤销函数
        private int i;
        private void Undo() 
        {
            i = i - 1;
            if (i > -1)
            {
                TreeNode AlreadyInsertName = new TreeNode();
                TreeNode SourceUpOneNode = new TreeNode();
                AlreadyInsertName = ((TreeNode)nDestNote[i]);
                SourceUpOneNode = ((TreeNode)nSource[i]);

                //记住变化后的节点Name,将变化后的重新移动到原来的位置(记住原来的Name上一个节点的Name位置(SourceUpOneNode)和插入后节点的name位置(AlreadyInsertName))
                //将AleadyInsertNode出入到SourceUpOneNode下面,将原来的删除

                AlreadyInsertName.Remove();
                
                SourceUpOneNode.Parent.Nodes.Insert(SourceUpOneNode.Index + 1, AlreadyInsertName);

                nDestNote.Remove((TreeNode)nDestNote[i]);
                nSource.Remove((TreeNode)nSource[i]);
            }
            else 
            {
                MessageBox.Show("已经撤消到了最后一步!");
            }

        }






    }
} --------------------编程问答-------------------- 这是我写的撤销程序,不过只有撤销的第一步是完全正确的,撤销多步都有Bug请高手帮忙指点!我真的有点急啊! --------------------编程问答-------------------- 我自己做了一个,完全没问题 --------------------编程问答-------------------- 那应该还可以恢复误删的节点还要保存删除节点子树,还要恢复误改的文字。。。

简单的做法是保存一份整个树的克隆

TreeView TV = new TreeView();
foreach (TreeNode Node in treeView1.Nodes)
   TV.Nodes.Add((TreeNode)Node.Clone());

要撤销,反过来
treeView1.Nodes.Clear();
foreach (TreeNode Node in TV.Nodes)
   treeView1.Nodes.Add((TreeNode)Node.Clone());
TV.Dispose(); 
--------------------编程问答-------------------- 设计模式 command模式 --------------------编程问答-------------------- public partial class Form1 : Form
    {
        public enum ChangeType
        {
            Add,
            Delete,
            Edit,
            Move,
            None
        }
        public class TreeNodeRecoding
        {
            public TreeNodeRecoding()
            {
                node = null;
                Parent = null;
                Index = -1;
                changeType = ChangeType.None;
            }

            public TreeNode node;
            public ChangeType changeType;
            public object Parent;
            public int Index;
        }

        
        public Form1()
        {
            InitializeComponent();
        }

        List<TreeNodeRecoding> tnrList = new List<TreeNodeRecoding>(); 

        TreeNode DraggingNode;
        TreeNode dragDestNode;

        private void treeView1_NodeMouseHover(object sender, TreeNodeMouseHoverEventArgs e)
        {
            if(DraggingNode !=null)
                dragDestNode  = e.Node;
        }

        private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DraggingNode = e.Item as TreeNode;
        }

        private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            this.treeView1.SelectedNode = e.Node;
        }


        


        /// <summary>
        /// 移动节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_MouseUp(object sender, MouseEventArgs e)
        {
            if (DraggingNode != null)
            {
                bool ex = false;
                if (dragDestNode.Parent == null)
                {
                    if (dragDestNode.Equals(DraggingNode))
                        ex = true;
                }
                else
                {
                    TreeNode temp = dragDestNode;
                    while (temp.Parent != null)//如果父节点不为空,往上一级查找以确定是否是子节点
                    {
                        temp = temp.Parent;
                        if (temp.Equals(DraggingNode))
                        {
                            ex = true;
                            break;
                        }
                    }
                } 

                if (!ex)
                {                   
                    treeView1.Nodes.Remove(DraggingNode);
                    Record(DraggingNode, ChangeType.Delete, DraggingNode.Parent == null ?(object) treeView1 :(object) DraggingNode.Parent, DraggingNode.Index);
                    try
                    {
                        int idx = dragDestNode.Index;
                        //int idx = dragDestNode.Parent.Nodes.IndexOf(dragDestNode);                        
                        dragDestNode.Parent.Nodes.Insert(idx, DraggingNode);
                        Record(null, ChangeType.Move, dragDestNode.Parent, idx);
                    }
                    catch
                    {
                        try
                        {
                            int idx = dragDestNode.Index;
                            //int idx = treeView1.Nodes.IndexOf(dragDestNode);
                            treeView1.Nodes.Insert(idx, DraggingNode);
                            Record(null, ChangeType.Move, treeView1, idx);
                        }
                        catch
                        {
                            UnDoTreeView();
                        }
                    }
                }
            }
            DraggingNode = null;
        }

        void Record(TreeNode tn,ChangeType ct,object parent,int idx )
        {
            if (tnrList.Count == 40)
            {
                if (tnrList[0].changeType == ChangeType.Delete)//如果是删除操作
                {
                    tnrList.Remove(tnrList[0]);
                    if (tnrList[0].changeType == ChangeType.Move)//检查前面一个是否是移动操作,如果是则一起删除
                    {
                        tnrList.Remove(tnrList[0]);
                    }
                }
                else
                    tnrList.Remove(tnrList[0]);
            }
            TreeNodeRecoding tnr = new TreeNodeRecoding();
            tnr.node = tn;
            tnr.changeType = ct;
            tnr.Parent = parent;
            tnr.Index = idx;

            tnrList.Add(tnr);
        }


         --------------------编程问答-------------------- void UnDoTreeView()
        {
            if (tnrList.Count == 0)
                MessageBox.Show("已经到了最后一步了");
            else
            {
                TreeNodeRecoding tnr = tnrList[tnrList.Count - 1];
                switch (tnr.changeType)
                {
                    case ChangeType.Move:
                        if (tnr.Parent is TreeView)
                        {
                            treeView1.Nodes.RemoveAt(tnr.Index);
                            //treeView1.Nodes.Remove(treeView1.Nodes[tnr.Index]);
                        }
                        else if (tnr.Parent is TreeNode)
                        {
                            (tnr.Parent as TreeNode).Nodes.RemoveAt(tnr.Index);
                            //(tnr.Parent as TreeNode).Nodes.Remove((tnr.Parent as TreeNode).Nodes[tnr.Index]);
                        }
                        tnrList.Remove(tnr);
                        UnDoTreeView();

                        break;
                    case ChangeType.Add :
                        if (tnr.Parent is TreeView)
                        {
                            treeView1.Nodes.Remove(treeView1.Nodes[tnr.Index]);
                        }
                        else if (tnr.Parent is TreeNode)
                        {
                            (tnr.Parent as TreeNode).Nodes.Remove((tnr.Parent as TreeNode).Nodes[tnr.Index]);
                        }
                        break;
                    case ChangeType.Delete:
                        if (tnr.Parent is TreeView)
                        {
                            treeView1.Nodes.Insert(tnr.Index,tnr.node);
                        }
                        else if (tnr.Parent is TreeNode)
                        {
                            (tnr.Parent as TreeNode).Nodes.Insert(tnr.Index,tnr.node);
                        }
                        break;
                    case ChangeType.Edit:
                        if (tnr.Parent is TreeView)
                        {
                            treeView1.Nodes[tnr.Index] = tnr.node;
                        }
                        else if (tnr.Parent is TreeNode)
                        {
                            (tnr.Parent as TreeNode).Nodes[tnr.Index] = tnr.node;
                        }
                        break;
                    default:
                        break;
                }
                tnrList.Remove(tnr);

            }
            
            


            //if(tnrList.Count ==0 )
            //    MessageBox.Show("已经到了最后一步了");
            //else
            //{
            //    //TreeNodeRecoding tnr = tnrList[tnrList.Count - 1];
            //    //if (tnr.curIndex != -1)//如果有新位置不为空,为添加操作
            //    //{
            //    //    if (tnr.oldIndex != -1)//如果旧位置不为空,为移动操作或编辑操作
            //    //    {
            //    //        if (tnr.oldIndex != tnr.curIndex) //如果新旧不相等,说明为移动操作
            //    //        {
            //    //            if (tnr.curParent is TreeView)
            //    //            {
            //    //                (tnr.curParent as TreeView).Nodes.Remove((tnr.curParent as TreeView).Nodes[tnr.curIndex]);
            //    //            }
            //    //            else if(tnr.curParent is TreeNode)
            //    //            {
            //    //                (tnr.curParent as TreeNode).Nodes.Remove((tnr.curParent as TreeNode).Nodes[tnr.curIndex]);
            //    //            }

            //    //            if (tnr.oldParent is TreeView)
            //    //            {
            //    //                (tnr.oldParent as TreeView).Nodes.Insert(tnr.oldIndex , tnr.node);
            //    //            }
            //    //            else if(tnr.oldParent is TreeNode)
            //    //            {
            //    //                (tnr.oldParent as TreeNode).Nodes.Insert(tnr.oldIndex, tnr.node);
            //    //            }

            //    //            tnrList.Remove(tnr);
            //    //        }
            //    //        else//编辑操作
            //    //        {

            //    //        }
            //    //    }
            //    //    else//如果旧位置为空,为单纯的添加操作
            //    //    {

            //    //    }
            //    //}
            //    //else//如果新位置为空,为删除操作
            //    //{

            //    //}
            //}
        }

        private void 添加子级ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                treeView1.SelectedNode.Nodes.Add("新建节点");
                Record(null, ChangeType.Add, treeView1.SelectedNode, treeView1.SelectedNode.Nodes.Count - 1);
            }
            catch
            {
                MessageBox.Show("请先选择要删除的节点");
            }
        }

        private void 删除记录ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                TreeNode tn = treeView1.SelectedNode;
                int idx = tn.Index;
                object p = tn.Parent ==null?(object)treeView1:(object)tn.Parent;
                treeView1.Nodes.Remove(treeView1.SelectedNode);
                Record(tn, ChangeType.Delete, p, idx);
            }
            catch
            {
                MessageBox.Show("请先选择要删除的节点");
            }
        }

        private void 插入记录ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                TreeNode newTn = new TreeNode();
                TreeNode tn = treeView1.SelectedNode;
                int idx = tn.Index;
                object p = tn.Parent == null ? (object)treeView1 : (object)tn.Parent;
                
                if (p is TreeView)
                {
                    treeView1.Nodes.Insert(idx, "新建节点");
                    newTn = treeView1.Nodes[idx];
                }
                else if (p is TreeNode)
                {
                    (p as TreeNode).Nodes.Insert(idx, "新建节点");
                    newTn =(p as TreeNode).Nodes[idx];
                }
                Record(newTn, ChangeType.Add, p, idx);
            }
            catch
            {
                MessageBox.Show("请先选择要删除的节点");
            }
        }

        private void 编辑节点ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                
            }
            catch
            {
                MessageBox.Show("请先选择要删除的节点");
            }
        }

        private void 撤销操作ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UnDoTreeView();
        }

        private void treeView1_Click(object sender, EventArgs e)
        {
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
} --------------------编程问答-------------------- 还不错撒,注意的是如果是移动操作的话要继续撤销,就差一个编辑操作了,很容易啦,提交之前保存内容,提交之后在记录中加入之前的保存就好了,
补充:.NET技术 ,  C#
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,