英文:
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("@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)
{
// I stored te json in a file
// Your api call would be here
string filePath = "data.json";
string json = File.ReadAllText(filePath);
// Get the Categories
var rootjson = JsonConvert.DeserializeObject<Root>(json);
List<ItemCategory> itemList = rootjson.Categories;
// Build the tree
var root = new TreeNode();
// I use a dictionary for lookup this could be done without
Dictionary<string, TreeNode> tree = new Dictionary<string, TreeNode>();
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($"{"".PadLeft(level * 2)}{node.Key} - {node.Value}");
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论