как клонировать TreeView C # и сохранить его, чтобы восстановить позже - PullRequest
2 голосов
/ 25 декабря 2010

Мне нужно клонировать весь древовидный список для реализации действий Отменить \ Повторить. Я пытаюсь по-разному, но кажется, что напрямую это невозможно. Я имею в виду копирование всего дерева, сохранение этой копии в списке. Затем, когда запрашивается действие «Отменить», уменьшите конкретный счетчик уровней отмены и замените фактическое древовидное представление древовидным, которое существует в позициях индекса списка. если я делаю повтор, происходит то же самое, но lvls увеличивается, поэтому я возвращаю то, что будет дальше. Каждый раз, когда в древовидной структуре происходят изменения, мне нужно сохранить эту копию и увеличить счетчик lvl

.

Ответы [ 4 ]

3 голосов
/ 25 декабря 2010

Я думаю, вам следует подумать об этом по-другому.

Вам не нужно хранить весь TreeView, чтобы отслеживать отмены и повторы.Вам нужно только отслеживать изменения:

  • Если вы добавляете узел, отмена состоит в том, чтобы удалить его, поэтому вам нужна только ссылка на этот узел.
  • Если выудалите его, отмените, чтобы добавить его, поэтому вам нужна ссылка на добавленный узел и узел, к которому он был добавлен.
  • Если вы удалите целую ветвь, то вам нужно сохранить ветвь и узелон был удален из.

и так далее.Я думаю, вам повезет, если вы сделаете это таким образом, чем пытаетесь сохранить все дерево.И я делал это таким образом в приложениях, где я реализовал отмену / повтор.

1 голос
/ 25 декабря 2010

Вместо клонирования самого дерева вы можете просто клонировать TreeNodes (см. TreeNode.Clone () ).Кажется, что важный бит - это связь между узлами, так что это, вероятно, сработает для вас (я говорю «вероятно», потому что на самом деле я сам этого не делал, поэтому я не могу сказать вам, есть ли какие-то предостережения, которые нужноопасаться).

0 голосов
/ 25 декабря 2010

Это мой выстрел, в памяти нет движущихся больших объектов:

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

    }
}
0 голосов
/ 25 декабря 2010

Рассмотрите возможность реализации Шаблон команды (GoF):

  • Поместите логику своих действий в классы, которые реализуют общий ICommand {Do ();Undo ();} interface.
  • При каждом пользовательском действии вы создаете объект запрошенной команды и инициализируете его с параметрами контекста, такими как новое и старое имя файла.
  • Вызов Do (), помещение объекта в стекзавершенных команд.
  • Каждая команда снабжена контекстом, поэтому, вызывая Undo (), она может отменить изменения.
  • Рассмотреть возможность перемещения файлов во временную папку вместо удаления.

Кроме того, для быстрого линейного отмены / повтора другим вариантом является шаблон Memento , использующий zip файла в качестве сувенира.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...