Member 12175492 Ответов: 2

Как сохранить мои состояния флажка treeview в файле формата json


Я пытаюсь сохранить свой список добавленных родительских и дочерних узлов древовидного представления в формируемом файле json - test.json. Я использовал вложенный цикл foreach, но он не давал мне правильного типа моего сохранения. Мой метод добавления выглядит следующим образом:
private void InitializeTreeView()
{
  treeView1.Nodes.Add(new TreeNode("chapter1") { Tag = @"\include {chap1}" }); ;
  treeView1.Nodes.Add(new TreeNode("chapter2") { Tag = @"\include {chap2}" });
  treeView1.Nodes.Add(new TreeNode("chapter3") { Tag = @"\include {chap3}" });
  treeView1.Nodes[1].Nodes.Add(new TreeNode("sec21") { Tag = @"\input {sec33}" });
  treeView1.Nodes[1].Nodes.Add(new TreeNode("section22") { Tag = @"\input {sec22}" });
  treeView1.Nodes[2].Nodes.Add(new TreeNode("section31") { Tag = @"\input{sec31}" });
}


Тогда мой файл конфигурации документа для форматирования JSON выглядит следующим образом:

public class DocPart
   {
      public string NodeTitle { get; set; }
      public bool NodeChecked { get; set; }
      public string ChildTitle { get; set; }
      public bool ChildChecked { get; set; }
   }

   public class DocConfig
   {
      public List<DocPart> Parts { get; set; }

       public static DocConfig LoadFromString(string jsonData)
       {
           var serializer = new DataContractJsonSerializer(typeof(DocConfig));

           var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
           var config = (DocConfig)serializer.ReadObject(ms);

           return config;

       }
       public string SaveToString()
       {
           var serializer = new DataContractJsonSerializer(typeof(DocConfig));
           var ms = new MemoryStream();
           serializer.WriteObject(ms, this);
           return Encoding.UTF8.GetString(ms.ToArray()).PrettyPrintJson();
       }
   }

Я удаляю ненужные родительские и дочерние узлы с помощью флажков click. Поэтому я хочу сохранить состояние флажка в своем файле test. json. Как я уже сказал, я пробовал вложенный цикл foreach, но он не дает мне правильных вариантов. Может быть, вы могли бы дать мне несколько советов, как правильно сохранить мой вид дерева? Моя попытка спасения:

private void SaveConfig(string path)
   {
       var config = new DocConfig();
       config.Parts = new List<DocPart>();


       foreach (TreeNode node in treeView1.Nodes)
       {
           {
           config.Parts.Add(new DocPart { NodeTitle = node.Text, NodeChecked = node.Checked });
           }

           foreach (TreeNode child in node.Nodes)
           {
           config.Parts.Add(new DocPart { ChildTitle = child.Text, ChildChecked = child.Checked });
           }
           var configString = config.SaveToString();
           File.WriteAllText(path, configString);

      }
   }

BillWoodruff

Это элемент управления Windows WinForm TreeView ?

Member 12175492

Это winForms

BillWoodruff

Я написал код, который сохраняет/восстанавливает весь TreeView (с любым количеством уровней), включая Checked и другие свойства. Но вы не можете сериализовать коллекцию WinForm TreeView TreeNodeCollection напрямую из-за природы элемента управления WinForms TreeView.

В вашем случае вам может не понадобиться сериализовать / де-сериализовать произвольно вложенную коллекцию TreeNodeCollection.

Ответ на эти вопросы поможет мне помочь вам:

1. что именно для вас важно сохранить и восстановить: весь TreeView, включая такие свойства, как Tag и Checked ? .. или ... что-то меньшее ?

2. Вы упомянули "удаление нежелательных родительских и дочерних узлов с помощью флажков": означает ли это, что вы не хотите сохранять/восстанавливать определенные узлы ? пожалуйста, проясните это.

3. Важно ли использовать JSON ? Будет ли WCF XML работать для вас ?

4. знаете ли вы, как рекурсивно анализировать TreeNodeCollection TreeView?

Member 12175492

1: Мой проект состоит в том, чтобы сделать руководство из глав(родительский узел) и разделов(дочерний узел), я хочу сделать свой конфигурационный файл документа, который написан в JSON, потому что я хочу сделать что-то вроде типа руководства. До которого я всегда мог добраться, используя его в качестве параметра командной строки. Это что-то вроде загрузки предыдущего сгенерированного руководства. Итак, о моих проблемах: я сохраняю все в файл json, но это неправильно. Он сохраняет каждый родительский и дочерний узлы как разные и не связанные части. Главное, я не знаю, как сделать так, чтобы родительский узел имел свои дочерние узлы.

2.In мое приложение я добавляю много глав и разделов. В моем случае я хочу сделать много типов сгенерированных документов. Поэтому иногда мне не нужны некоторые главы или разделы в моем документе.

3. Да, мне это нужно в Json.

4.я много искал, как разобрать мою treeNodecollection. И много предложений было сделать это рекурсивно. Но я пробовал и не удалось сделать это.

BillWoodruff

"2.In мое приложение я добавляю много глав и разделов. В моем случае я хочу сделать много типов сгенерированных документов. Поэтому иногда мне не нужны некоторые главы или разделы в моем документе."

Одна из проблем заключается в том, как сохранить и восстановить древовидное изображение именно таким, как оно есть. Вопрос о том, как сгенерировать какой-то документ, проанализировав TreeView и используя "проверенное значение флажков узла", чтобы определить, что будет добавлено в документ или исключено из него ... это другой вопрос.

Флажок в каждом TreeNode в WinForms TreeView "независим" от любого другого флажка: вы можете с помощью кода убедиться, что все дочерние узлы, наследующие от данного узла, имеют значения флажков, равные их родительским.

Member 12175492

Основная проблема заключается в том, что в моем json-файле каждый узел похож на один флажок, он имеет 4 части childtitle, nodetitle, childchecked и nodechecked. Если это родительский узел, то nodetitle говорит имя этого узла и проверяет состояние, но дочерний узел получает нулевое значение. В другом варианте, если узел является дочерним, он получает статус childtitle и childchecked, но он получает нулевое значение nodetitle (родительский узел) и каждый раз false nodechecked. И сначала я пытаюсь это изменить.

BillWoodruff

Я посмотрел на JSON, созданный вашим примером кода: Вы не сохраняете информацию, которая позволила бы вам сбросить отношения родитель-потомок, поэтому вы никогда не сможете воссоздать древовидную структуру из этого JSON.

Member 12175492

да, наверное, мне следует использовать рекурсию, но, может быть, вы дадите мне несколько советов, как это сделать для моего примера?

BillWoodruff

Все, что я знаю, что может помочь вам (кроме написания вашего кода для вас), находится в решении, которое я опубликовал здесь.

Member 12175492

о'кей, спасибо

BillWoodruff

Вот "указатель": что вам нужно сделать, чтобы ваш JSON выглядел так:

{
"Комплектующие":
[
{"ChildChecked": false, "ChildTitle":null, "NodeChecked":false,"NodeParent":null, "NodeTitle": "chapter1"},

{"ChildChecked": false, "ChildTitle":null, "NodeChecked":false,"NodeParent":null, "NodeTitle": "chapter2"},

{"ChildChecked":false,"ChildTitle":"sec21","NodeChecked":false,"NodeParent":"chapter2","NodeTitle":null},

{"ChildChecked":false,"ChildTitle":"section22","NodeChecked":false,"NodeParent":"chapter2","NodeTitle":null},

{"ChildChecked": false, "ChildTitle":null, "NodeChecked":false,"NodeParent":null, "NodeTitle": "chapter3"},

{"ChildChecked":false,"ChildTitle":"section31","NodeChecked":false,"NodeParent":"chapter3","NodeTitle":null}
]
}

Теперь подумайте, что вы де-сериализовали этот JSON обратно в объект DocConfig: что вам нужно сделать, чтобы восстановить структуру узлов TreeView ?

Причина, по которой я призываю вас подумать об использовании рекурсии, а не жестко запрограммированного двухуровневого решения, заключается в следующем: Я верю, что в будущем освоение сохранения и восстановления иерархических структур может принести вам большую выгоду. И даже в вашем сценарии здесь, что происходит, когда вы хотите добавить дополнительные уровни дочерних узлов: ну, вам придется все переделать.

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

твое здоровье, Билл

Member 12175492

Так ты можешь мне помочь?

BillWoodruff

См. мой второй комментарий выше.

2 Ответов

Рейтинг:
2

Iris Panabaker

Я бы рекомендовал использовать такие инструменты JSON, как https://codebeautify.org/jsonviewer и https://jsonformatter.org для отладки, просмотра и проверки данных JSON.


Рейтинг:
1

BillWoodruff

Я не собираюсь публиковать здесь полный рабочий код, так как код, который я написал для этого сценария, был сделан для клиента. То, что я собираюсь опубликовать, - это общий план того, как вы можете добиться сохранения/восстановления TreeNodes в WinForms TreeView с помощью JSON.

О. вы начинаете с простого класса для моделирования TreeNode:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Windows.Forms;

// in your NameSpace

[DataContract]
public class TNode
{
    [DataMember]
    public TNode Parent { set; get; }

    [DataMember]
    public string Text { set; get; }

    [DataMember]
    public string Tag { set; get; }

    [DataMember]
    public bool CState { set; get; }

    public TNode(TNode parent, string txt, bool cstate, string tag)
    {
        Parent = parent;
        Text = txt;
        CState = cstate;
        Tag = tag;
    }
}
Вы заметите, что узел "модель" здесь не имеет списка дочерних узлов: это по замыслу, и "воскрешение" правильных отношений родитель-потомок зависит от определенного использования рекурсии.

B. Затем класс, который будет содержать коллекцию моделей TreeNode:"
[DataContract]
public class TNodeCollection
{
    [DataMember]
    public List<TNode> NodeCollection { set; get; }

    public TNodeCollection(TreeNodeCollection nodes)
    {
        NodeCollection = new List<TNode>();

        // for you to write
        ParseTree(null, nodes);
    }

    // for you to write
    //public void SaveJSON() { ... } 
    //public void RestoreJSON(TreeView tv) { ... }

    // to be continued
}
Если у вас есть этот "плоский список" создан TNodes, это простое дело, чтобы сэкономить, что в JSON-формате, и чтобы прочитать его обратно из JSON.

Интересная часть заключается в том, как вы воссоздаете из Де-сериализованного плоского списка правильные отношения родительского и дочернего узлов. Это достигается за счет использования того факта, что модели узлов создаются с помощью рекурсии глубины первой при разборе TreeView TreeNodeCollection: так как родительские узлы будут созданы до их дочерние узлы мы можем использовать TreeNodeCollection.Метод Find ("nodename", true) позволяет найти родительский узел при чтении дочернего узла, а затем установить родительский узел дочернего узла.

Ваш код в форме, где вы хотите сохранить / сериализовать TreeView, может выглядеть следующим образом:
TNodeCollection coll = new TNodeCollection(treeView1.Nodes);

coll.SaveJSON();

coll.RestoreJSON(treeView1);