如何克隆treeview c#并将其保存以便以后恢复

时间:2010-12-24 21:50:47

标签: c# winforms treeview

我需要克隆整个树视图以实现Undo \ Redo操作。我以不同的方式尝试,但看起来直接是不可能的。我的意思是复制整个树视图,将该副本保存在列表中。然后,当请求撤消操作时,递减撤消级别的特定计数器,并将实际树视图替换为列表的索引位置中存在的树视图。如果我做重做同样的事情发生但lvls增加所以我恢复接下来的事情。每次在树视图中发生修改时,我都需要保存该副本并增加lvl计数器

4 个答案:

答案 0 :(得分:3)

我认为你应该考虑以不同的方式解决这个问题。

您无需存储整个TreeView以跟踪撤消和重做。您只需要跟踪更改:

  • 如果添加节点,则撤消将删除它,因此您只需要对该节点的引用。
  • 如果删除它,则撤消是添加它,因此您需要引用添加的节点及其添加的节点。
  • 如果删除整个分支,则需要存储分支及其删除的节点。

等等。我认为你这样做会比尝试存储整棵树更好运。我已经在我已经实现了undo / redo的应用程序中这样做了。

答案 1 :(得分:1)

您可以简单地克隆TreeNodes而不是克隆树视图(请参阅TreeNode.Clone())。似乎重要的一点是节点之间的关系,所以这可能对你有用(我说“可能”因为我自己实际上没有这样做,所以我不能告诉你是否有任何警告是警惕)。

答案 2 :(得分:0)

考虑实施Command pattern(GoF):

  • 将您的操作逻辑放入类中 实现常见的ICommand {做(); Undo();} interface。
  • 在每个用户操作上创建对象 命令请求并初始化 它与上下文参数如新 和旧文件名。
  • 调用Do(),将对象放入堆栈中 已完成的命令。
  • 提供每个命令 上下文,所以通过调用Undo()它可以 逆转。
  • 考虑将文件移动到临时文件中 文件夹而不是删除。

此外,对于快速线性撤消/重做,另一个选项是使用文件zip作为纪念品的Memento pattern

答案 3 :(得分:0)

这是我的镜头,没有大的物体被移动到记忆中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;

namespace treeundoredo
{
    static class Program
    {
        static TreeNode GetNode(string id, TreeNodeCollection root)
        {
            foreach (TreeNode node in root)
                if (node.Text == id)
                    return node;
                else
                {
                    var subnode = GetNode(id, node.Nodes);
                    if (subnode != null)
                        return subnode;
                }

            return null;
        }

        [STAThread]
        static void Main()
        {
            // list of (node, parent)
            List<KeyValuePair<string, string>> undo = new List<KeyValuePair<string, string>>(), redo = new List<KeyValuePair<string, string>>();

            Random rng = new Random();
            TreeView Tree = new TreeView() { Size = new Size(200, 250) };
            Tree.Nodes.Add("Root");
            Tree.NodeMouseClick += (s, e) => { undo.Add(new KeyValuePair<string, string>(e.Node.Nodes.Add(rng.Next().ToString()).Text, e.Node.Text)); Tree.ExpandAll(); redo.Clear(); };

            Button Undo = new Button() { Text = "Undo", Left = 205 };
            Undo.Click += (s, e) => { if (undo.Count > 0) { var kvp = undo[undo.Count - 1]; GetNode(kvp.Key, Tree.Nodes).Remove(); redo.Add(kvp); undo.Remove(kvp); } };

            Button Redo = new Button() { Text = "Redo", Left = 205, Top = 50 };
            Redo.Click += (s, e) => { if (redo.Count > 0) { var kvp = redo[redo.Count - 1]; GetNode(kvp.Value, Tree.Nodes).Nodes.Add(kvp.Key); redo.Remove(kvp); undo.Add(kvp); Tree.ExpandAll(); } };

            Form frm = new Form();
            frm.Controls.AddRange(new Control[] { Tree, Undo, Redo });
            Application.Run(frm);
        }

    }
}