我需要克隆整个树视图以实现Undo \ Redo操作。我以不同的方式尝试,但看起来直接是不可能的。我的意思是复制整个树视图,将该副本保存在列表中。然后,当请求撤消操作时,递减撤消级别的特定计数器,并将实际树视图替换为列表的索引位置中存在的树视图。如果我做重做同样的事情发生但lvls增加所以我恢复接下来的事情。每次在树视图中发生修改时,我都需要保存该副本并增加lvl计数器
答案 0 :(得分:3)
我认为你应该考虑以不同的方式解决这个问题。
您无需存储整个TreeView以跟踪撤消和重做。您只需要跟踪更改:
等等。我认为你这样做会比尝试存储整棵树更好运。我已经在我已经实现了undo / redo的应用程序中这样做了。
答案 1 :(得分:1)
您可以简单地克隆TreeNodes而不是克隆树视图(请参阅TreeNode.Clone())。似乎重要的一点是节点之间的关系,所以这可能对你有用(我说“可能”因为我自己实际上没有这样做,所以我不能告诉你是否有任何警告是警惕)。
答案 2 :(得分:0)
考虑实施Command pattern(GoF):
此外,对于快速线性撤消/重做,另一个选项是使用文件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);
}
}
}