2016-09-24 4 views
3

У меня есть дерево winforms, я могу читать данные автоматически (узел, равный ключу, и узел внутри которого равен значению), но при чтении типа объекта, значения внутри него не будут дочерними узлами объекта (ключом объекта), (может быть, я не мог хорошо объяснить, вот скриншот и мои методы.)Как рекурсивно заполнять TreeView с данными JSON

layer0 должен быть внутри текстур, и масштаб должен быть внутри дисплея

layer0 needs to be inside textures and scale needs to be inside display

Мои Json:

{ 
"parent": "builtin/generated", 
"textures": { 
    "layer0": "mm:items/iron_dust" 
}, 
"display": {  
     "scale": [ 1.7, 1.7, 1.7 ] 
} 
} 

Мой метод автоматического обнаружения (не все мои на самом деле)

private void Form1_Load(object sender, EventArgs e) 
    { 
     StreamReader reader = new StreamReader(path); 
     string json = reader.ReadToEnd(); 
     reader.Close(); 
     JObject obj = JObject.Parse(json); 
     getAllProperties(obj); 
    } 

    void getAllProperties(JToken children) 
    { 
     TreeNode mainNode = treeView1.Nodes[0]; 
     mainNode.Text = Path.GetFileNameWithoutExtension(path); 
     foreach (JToken child in children.Children()) 
     { 
      var property = child as JProperty; 
      if (property != null) 
      { 
       if (property.Value.Type == JTokenType.String) 
       { 
        TreeNode keyNode = mainNode.Nodes.Add(property.Name); 
        keyNode.Nodes.Add(property.Value.ToString()); 
       } 
       if (property.Value.Type == JTokenType.Array) 
       { 
        JArray array = (JArray)property.Value; 
        TreeNode node = mainNode.Nodes.Add(property.Name); 
        for (int i = 0; i < array.Count; i++) 
        { 
         node.Nodes.Add(array[i].ToString()); 
        } 
       } 
       if (property.Value.Type == JTokenType.Object) 
       { 
        TreeNode topNode = mainNode.Nodes.Add(property.Name.ToString()); 
        foreach (var item in property) 
        { 
         if (item.Type == JTokenType.String) 
         { 
          if (property.Value.Type == JTokenType.String) 
       { 
        TreeNode keyNode = topNode.Nodes.Add(property.Name); 
        keyNode.Nodes.Add(property.Value.ToString()); 
       } 
       if (property.Value.Type == JTokenType.Array) 
       { 
        JArray array = (JArray)property.Value; 
        TreeNode node = topNode.Nodes.Add(property.Name); 
        for (int i = 0; i < array.Count; i++) 
        { 
         node.Nodes.Add(array[i].ToString()); 
        } 
       } 
         } 
        } 
       } 


        // Console.WriteLine(property.Name + ":" + property.Value);//print all of the values 
       } 
       getAllProperties(child); 
      } 
     } 

    } 

Я попытался получить родителя, но оно не имеет имя и значение свойства: S. Любая помощь? (Извините за язык ошибок)

+1

Может быть, [этот поток] (http://stackoverflow.com/questions/16181298/how-to-do-recursive-descent-of-json-using-json-net) может помочь? –

+0

Я постараюсь, когда смогу :) (я не могу попробовать сейчас) Но .. я не понимаю, что здесь делает walknode. Не могли бы вы объяснить, пожалуйста? –

+1

'WalkNode' работает следующим образом: получает узел из аргумента, затем выполняет итерацию по каждому дочернему узлу узла. Он применяет функцию «Действие» (которая может быть добавлена ​​к MainNode в вашем случае), а затем идет уровень глубже - calss 'WalkNode' на дочернем элементе. В принципе, он рекурсивно ходит по всем узлам в JSON. –

ответ

5

Проблема заключается в том, что, как вы рекурсивно спускаться по JToken иерархии, также необходимо рекурсивно спускаться по TreeNode иерархии вы создаете, добавление дочерних узлов к родительскому узлу только что созданный, а не корневой узел, по линиям Recursion, parsing xml file with attributes into treeview c#.

Таким образом, если вы:

private void Form1_Load(object sender, EventArgs e) 
    { 
     using (var reader = new StreamReader(path)) 
     using (var jsonReader = new JsonTextReader(reader)) 
     { 
      var root = JToken.Load(jsonReader); 
      DisplayTreeView(root, Path.GetFileNameWithoutExtension(path)); 
     } 
    } 

    private void DisplayTreeView(JToken root, string rootName) 
    { 
     treeView1.BeginUpdate(); 
     try 
     { 
      treeView1.Nodes.Clear(); 
      var tNode = treeView1.Nodes[treeView1.Nodes.Add(new TreeNode(rootName))]; 
      tNode.Tag = root; 

      AddNode(root, tNode); 

      treeView1.ExpandAll(); 
     } 
     finally 
     { 
      treeView1.EndUpdate(); 
     } 
    } 

    private void AddNode(JToken token, TreeNode inTreeNode) 
    { 
     if (token == null) 
      return; 
     if (token is JValue) 
     { 
      var childNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(token.ToString()))]; 
      childNode.Tag = token; 
     } 
     else if (token is JObject) 
     { 
      var obj = (JObject)token; 
      foreach (var property in obj.Properties()) 
      { 
       var childNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(property.Name))]; 
       childNode.Tag = property; 
       AddNode(property.Value, childNode); 
      } 
     } 
     else if (token is JArray) 
     { 
      var array = (JArray)token; 
      for (int i = 0; i < array.Count; i++) 
      { 
       var childNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(i.ToString()))]; 
       childNode.Tag = array[i]; 
       AddNode(array[i], childNode); 
      } 
     } 
     else 
     { 
      Debug.WriteLine(string.Format("{0} not implemented", token.Type)); // JConstructor, JRaw 
     } 
    } 

Вы получите следующую структуру в виде дерева:

enter image description here

+0

Whoa! Это то, что мне нужно. Но я кое-что удивляюсь. Это работает для booleans: if (token is JBoolean) {var childNode = inTreeNode.Nodes [inTreeNode.Nodes.Add (новый TreeNode (токен.ToString())]]; childNode.Tag = token;} –

+1

Нет такой вещи, как 'JBoolean'. Булевы хранятся в 'JValue'. Набор всех конкретных типов linq-to-JSON показан в [этом ответе] (https://stackoverflow.com/questions/23812357/how-to-bind-dynamic-json-into-treeview-wpf/28097883#28097883). – dbc

Смежные вопросы