【问题标题】:how to clone a treeview c# and save it to recover later如何克隆一个treeview c#并将其保存以便以后恢复
【发布时间】:2010-12-24 21:50:46
【问题描述】:

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

【问题讨论】:

  • 这是 WinForms 将演示文稿与数据联系起来的方法的一个问题。换一种方式想它;修改基础数据并找出将其传播到 UI 的方法。
  • nop,treeview 的组织是驱动我的应用程序行为的原因,不是相反,至少对于这个特定情况

标签: c# winforms treeview


【解决方案1】:

我认为你应该考虑换一种方式来解决这个问题。

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

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

等等。我认为这样做比尝试存储整棵树更幸运。我已经在我实现了撤消/重做的应用程序中这样做了。

【讨论】:

  • 是的,你的权利我的想法实际上是蛮力,我会考虑你的建议。该树还带来了将任何子树移动和复制到任何子树的可能性,因此使用您所说的跟踪更改的组合可以帮助我定义此操作。我也有兴趣撤消重做任何展开/折叠操作。
  • 您可能会发现我对这个问题的回答有助于了解有关如何实施撤消/重做的更多详细信息:stackoverflow.com/questions/2058146/…
【解决方案2】:

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

【讨论】:

  • 谢谢!它有效,我无法通过我的简单探索找到 Clone 方法,因为我忘记将 foreach 循环中的“var”关键字更改为相应的 TreeNode 类型 T_T。现在我在想如何保存他的扩展状态,因为它们在副本中丢失,恢复,处理
【解决方案3】:

考虑实施Command pattern (GoF):

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

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

【讨论】:

    【解决方案4】:

    这是我的镜头,内存中没有大的物体被移动:

    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);
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-16
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      • 2010-12-23
      相关资源
      最近更新 更多