父子节点选择

huangapple go评论85阅读模式
英文:

Parent-Child Node Selection

问题

我正在开发一个C#应用程序,其中的一个方法用于检索OData响应体,这些响应体表示项目类别。任何父子关系都是通过Parent_Category元素定义的。

我的最终目标是向用户呈现项目类别的树形视图,以显示层次结构。就像这样。

父子节点选择

以下是发送给我的OData响应体。

{
"@odata.context": "https://api.businesscentral.dynamics.com/v2.0/13bb3475-ed48-4836-8e0d-6188cc004599/Sandbox2/ODataV4/$metadata#Company('CRONUS%20USA%2C%20Inc.')/ItemCategories",
"value": [
{
"@odata.etag": "W/"JzE5Ozc0MDEzNzM2MzQ2Mjc3MDQ5MzQxOzAwOyc="",
"Code": "BEANS",
"Description": "BEANS",
"Parent_Category": "",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzE4OzU5MTI1NDIzNTQ4MDU4MDc2OTE7MDA7Jw=="",
"Code": "CM",
"Description": "咖啡机",
"Parent_Category": "",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzE3MzEyMjA5NzY5NzA2NzQ1MjYyMTswMDsn"",
"Code": "CM_COMMER",
"Description": "商用型号",
"Parent_Category": "CM",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzE4OzkyNzkxOTcxNzAyNjYyMTI3ODE7MDA7Jw=="",
"Code": "CM_CONSUM",
"Description": "家用型号",
"Parent_Category": "CM",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzEyODQzNzYyMTU3OTI4NTE5Mzk1MTswMDsn"",
"Code": "FASHION",
"Description": "时尚珠宝",
"Parent_Category": "",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzEyMjU5NzE2Njg0MzE3ODg3MTc4MTswMDsn"",
"Code": "FURNITURE",
"Description": "办公家具",
"Parent_Category": "",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzE0NTg1NTU0Njg2NjkzNzc2MjM1MTswMDsn"",
"Code": "CHAIR",
"Description": "办公椅子",
"Parent_Category": "FURNITURE",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzE4OzkyMzYzNjkwNTExMzY3MzAwMDE7MDA7Jw=="",
"Code": "DESK",
"Description": "办公桌",
"Parent_Category": "FURNITURE",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzExNzIzNjI3NzUxMjcxMTI2MjY3MTswMDsn"",
"Code": "TABLE",
"Description": "各种桌子",
"Parent_Category": "FURNITURE",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzE2Ozc3MjM1ODY4ODY4MDQyNjcxOzAwOyc="",
"Code": "MISC",
"Description": "杂项",
"Parent_Category": "",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzE5OzU0NjM3MTMyNTc0NDI5MDk4NDIxOzAwOyc="",
"Code": "SUPPLIERS",
"Description": "办公用品",
"Parent_Category": "MISC",
"LSE_Outbound_Code": ""
},
{
"@odata.etag": "W/"JzIwOzEyNDU4NDkzNDczMDM2NjAxNDk4MTswMDsn"",
"Code": "PARTS",
"Description": "零件",
"Parent_Category": "",
"LSE_Outbound_Code": ""
}
]
}

有关我可以开始拆分这些内容的任何建议吗?在涉及结果的用户界面方面之前,甚至对它们进行文本列表化将是一个好的开始。比如:

BEANS
CM
--> CM_COMMER
--> CM_CONSUM
...

我想我需要将这些元素添加到一个列表中,然后通过递归遍历它们。只是在思考过程中开始有些困难。

英文:

So I have a C# app I'm working on, which for one method retrieves an OData response body. These represent item categories. Any parent-child relationship is defined with a Parent_Category element.

My ultimate goal is to present the user with a tree view of the item categories. So that the hierarchy is apparent. Like this.

父子节点选择

Below is the OData response body that's being sent back to me.

{
"@odata.context": "https://api.businesscentral.dynamics.com/v2.0/13bb3475-ed48-4836-8e0d-6188cc004599/Sandbox2/ODataV4/$metadata#Company('CRONUS%20USA%2C%20Inc.')/ItemCategories",
"value": [
    {
        "@odata.etag": "W/\"JzE5Ozc0MDEzNzM2MzQ2Mjc3MDQ5MzQxOzAwOyc=\"",
        "Code": "BEANS",
        "Description": "BEANS",
        "Parent_Category": "",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzE4OzU5MTI1NDIzNTQ0MDU4MDc2OTE7MDA7Jw==\"",
        "Code": "CM",
        "Description": "Coffee Makers",
        "Parent_Category": "",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzIwOzE3MzEyMjA5NzY5NzA2NzQ1MjYyMTswMDsn\"",
        "Code": "CM_COMMER",
        "Description": "Commercial Models",
        "Parent_Category": "CM",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzE4OzkyNzkxOTcxNzAyNjYyMTI3ODE7MDA7Jw==\"",
        "Code": "CM_CONSUM",
        "Description": "Consumer Models",
        "Parent_Category": "CM",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzIwOzEyODQzNzYyMTU3OTI4NTE5Mzk1MTswMDsn\"",
        "Code": "FASHION",
        "Description": "Fashion Jewelry",
        "Parent_Category": "",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzIwOzEyMjU5NzE2Njg0MzE3ODg3MTc4MTswMDsn\"",
        "Code": "FURNITURE",
        "Description": "Office Furniture",
        "Parent_Category": "",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzIwOzE0NTg1NTU0Njg2NjkzNzc2MjM1MTswMDsn\"",
        "Code": "CHAIR",
        "Description": "Office Chair",
        "Parent_Category": "FURNITURE",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzE4OzkyMzYzNjkwNTExMzY3MzAwMDE7MDA7Jw==\"",
        "Code": "DESK",
        "Description": "Office Desk",
        "Parent_Category": "FURNITURE",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzIwOzExNzIzNjI3NzUxMjcxMTI2MjY3MTswMDsn\"",
        "Code": "TABLE",
        "Description": "Assorted Tables",
        "Parent_Category": "FURNITURE",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzE2Ozc3MjM1ODY4ODY4MDQyNjcxOzAwOyc=\"",
        "Code": "MISC",
        "Description": "Miscellaneous",
        "Parent_Category": "",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzE5OzU0NjM3MTMyNTc0NDI5MDk0NDIxOzAwOyc=\"",
        "Code": "SUPPLIERS",
        "Description": "Office Supplies",
        "Parent_Category": "MISC",
        "LSE_Outbound_Code": ""
    },
    {
        "@odata.etag": "W/\"JzIwOzEyNDU0NDkzNDczMDM2NjAxNDk4MTswMDsn\"",
        "Code": "PARTS",
        "Description": "Parts",
        "Parent_Category": "",
        "LSE_Outbound_Code": ""
    }
]

}

Any suggestions about where I can start breaking these out? Before I get into the UI aspects of the result, even a text listing of them would be a start. Such as:

BEANS<br>
CM<br>
--> CM_COMMER<br>
--> CM_CONSUM<br>
...

I figure I need to add these elements into a List and then recursively iterate through that. Just having trouble getting started on the thought process.

答案1

得分: 1

以下是您要翻译的代码部分:

这是我能想到的最简单的方法。正如评论中所链接的,可能有更好的选项来从平面列表创建类似树状结构的内容。但这是完整的:

使用 Newtonsoft.Json;

public class Root
{
    [JsonProperty("@odata.context")]
    public string OdataContext { get; set; }

    [JsonProperty("value")]
    public List<ItemCategory> Categories { get; set; }
}

public class ItemCategory
{
    public string Code { get; set; }
    public string Description { get; set; }
    public string Parent_Category { get; set; }
}

public class TreeNode
{
    public string Key { get; set; }
    public string Value { get; set; }
    public List<TreeNode> Children { get; set; }

    public TreeNode()
    {
        Children = new List<TreeNode>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 我将 JSON 存储在文件中
        // 这里将是您的 API 调用位置
        string filePath = "data.json";
        string json = File.ReadAllText(filePath);

        // 获取类别
        var rootjson = JsonConvert.DeserializeObject<Root>(json);
        List<ItemCategory> itemList = rootjson.Categories;

        // 构建树
        var root = new TreeNode();

        // 我使用字典进行查找,这可以在没有字典的情况下完成
        Dictionary<string, TreeNode> tree = new Dictionary<string, TreeNode>();

        foreach (var category in itemList)
        {
            // 创建节点
            var treeNode = new TreeNode
            {
                Key = category.Code,
                Value = category.Description
            };

            // 添加节点
            if (string.IsNullOrEmpty(category.Parent_Category))
            {
                root.Children.Add(treeNode);
            }
            else
            {
                // 如果找到了父节点,将当前类别添加到 Children 列表中。
                if (tree.TryGetValue(category.Parent_Category, out var parent))
                {
                    parent.Children.Add(treeNode);
                }
            }

            tree.Add(category.Code, treeNode);
        }

        PrintTree(root, 0);
    }

    static void PrintTree(TreeNode node, int level)
    {
        // PadLeft 用于缩进
        Console.WriteLine($"{"".PadLeft(level * 2)}{node.Key} - {node.Value}");

        foreach (var child in node.Children)
        {
            PrintTree(child, level + 1);
        }
    }
}

打印结果:

      BEANS - BEANS
CM - Coffee Makers
CM_COMMER - Commercial Models
CM_CONSUM - Consumer Models
FASHION - Fashion Jewelry
FURNITURE - Office Furniture
CHAIR - Office Chair
DESK - Office Desk
TABLE - Assorted Tables
Test - Office Supplies //注意我添加了一个第三级的测试
MISC - Miscellaneous
SUPPLIERS - Office Supplies
PARTS - Parts
英文:

This is the easiest i can think of. As linked in the comments there might be better options for creating a tree like structure from a flat list. However this is complete:

using Newtonsoft.Json;
public class Root
{
[JsonProperty(&quot;@odata.context&quot;)]
public string OdataContext { get; set; }
[JsonProperty(&quot;value&quot;)]
public List&lt;ItemCategory&gt; Categories { get; set; }
}
public class ItemCategory
{
public string Code { get; set; }
public string Description { get; set; }
public string Parent_Category { get; set; }
}
public class TreeNode
{
public string Key { get; set; }
public string Value { get; set; }
public List&lt;TreeNode&gt; Children { get; set; }
public TreeNode()
{
Children = new List&lt;TreeNode&gt;();
}
}
class Program
{
static void Main(string[] args)
{
// I stored te json in a file 
// Your api call would be here
string filePath = &quot;data.json&quot;;
string json = File.ReadAllText(filePath);
// Get the Categories
var rootjson = JsonConvert.DeserializeObject&lt;Root&gt;(json);
List&lt;ItemCategory&gt; itemList = rootjson.Categories;
// Build the tree
var root = new TreeNode();
// I use a dictionary for lookup this could be done without 
Dictionary&lt;string, TreeNode&gt; tree = new Dictionary&lt;string, TreeNode&gt;();
foreach (var category in itemList)
{
// Create the node 
var treeNode = new TreeNode
{
Key = category.Code,
Value = category.Description
};
// Add the node 
if (string.IsNullOrEmpty(category.Parent_Category))
{
root.Children.Add(treeNode);
}
else
{
// If the parent is found, the current category is added to Children list.
if (tree.TryGetValue(category.Parent_Category, out var parent))
{
parent.Children.Add(treeNode);
}
}
tree.Add(category.Code, treeNode);
}
PrintTree(root, 0);
}
static void PrintTree(TreeNode node, int level)
{         
// PadLeft does the indentation              
Console.WriteLine($&quot;{&quot;&quot;.PadLeft(level * 2)}{node.Key} - {node.Value}&quot;);
foreach (var child in node.Children)
{
PrintTree(child, level + 1);
}
}
}

Prints :

  BEANS - BEANS
CM - Coffee Makers
CM_COMMER - Commercial Models
CM_CONSUM - Consumer Models
FASHION - Fashion Jewelry
FURNITURE - Office Furniture
CHAIR - Office Chair
DESK - Office Desk
TABLE - Assorted Tables
Test - Office Supplies //Note i added a 3rd lvl for test
MISC - Miscellaneous
SUPPLIERS - Office Supplies
PARTS - Parts

huangapple
  • 本文由 发表于 2023年6月29日 02:17:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575744.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定