Csharp: TreeNode
c# - How can I draw iterating ul-li List pattern? - Stack Overflow
https://pastehtml.com/view/dd9ttlh4x.html
what is the best approach to implement Tree View?<ul> <li>Level 1 a - Pastebin.com
How To Create Multi Level Menu Dynamically Using C# in ASP.NET - CodeProject
An ASP.NET AJAX TreeView control with templates - CodeProject
Auto-TOC Generation and Header Numbering - Revision - CodeProject
https://www.c-sharpcorner.com/article/create-jstree-simply/
https://gijgo.com/tree/demos/bootstrap-treeview
https://www.codeproject.com/articles/42861/amenu-a-simple-net-vertical-menu
https://www.cnblogs.com/Mryjp/p/easyui_tree.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | using System; using System.Collections.Generic; namespace TreeUtility { /// <summary> ///https://www.codeproject.com/articles/23949/building-trees-from-lists-in-net /// An object which implements this interface is considered a node in a tree. /// </summary> public interface ITreeNode<T> where T : class { /// <summary> /// A unique identifier for the node. /// </summary> int Id { get ; } /// <summary> /// The parent of this node, or null if it is the root of the tree. /// </summary> T Parent { get ; set ; } /// <summary> /// The children of this node, or an empty list if this is a leaf. /// </summary> IList<T> Children { get ; set ; } } /// <summary> /// A helper class for objects which implement <see cref="ITreeNode{T}"/>, providing /// methods to convert flat lists to and from hierarchical trees, iterators, and /// other utility methods. /// </summary> public static class TreeHelper { #region Tree structure methods /// <summary> /// Converts an array of ITreeNode objects into a forest of trees. The returned list will /// contain only the root nodes, with each root having a populated <see cref="ITreeNode{T}.Children">Children</see> /// property. /// </summary> /// <param name="flatNodeList"> /// An array of list of node objects, where the <see cref="ITreeNode{T}.Parent">Parent</see> /// property of each node is either null for root nodes, or an instantiated object with its /// <see cref="ITreeNode{T}.Id">Id</see> property set. /// </param> public static IList<T> ConvertToForest<T>( this IEnumerable<T> flatNodeList) where T : class , ITreeNode<T> { // first, put every TreeNode into a dictionary so that we can easily find tree nodes later. Dictionary< int , T> dictionary = new Dictionary< int , T>(); foreach (T node in flatNodeList) { dictionary.Add(node.Id, node); // while we're looping, it's a good time to create the Children list node.Children = new List<T>(); } // Now, go through each TreeNode. If Parent is null, then it is a root node of a tree, // so add it to the 'rootNodes' List, which is what will be returned from this method. // If Parent is not null, then find the parent from the dictionary, and set that to be it's Parent. List<T> rootNodes = new List<T>(); foreach (T node in flatNodeList) { if (node.Parent == null ) { // this is a root node; add it to the rootNodes list. rootNodes.Add(node); } else { // this is not a root node; add it as a child of its parent. if (!dictionary.ContainsKey(node.Parent.Id)) { // In this case, this node's parent is not in the flatNodeList. // By continuing, we are just ignoring this node (it won't be // returned in the tree). Another option would be to throw an // exception here. continue ; } // make the parent reference for this node a reference to a fully populated parent. node.Parent = dictionary[node.Parent.Id]; // add this node to the child list of its parent. node.Parent.Children.Add(node); } } return rootNodes; } /// <summary> /// Converts a heirachacle Array of Tree Nodes into a flat array of nodes. The order /// of the returned nodes is the same as a depth-first traversal of each tree. /// </summary> /// <remarks>The relationships between Parent/Children are retained.</remarks> public static List<T> ConvertToFlatArray<T>( this IEnumerable<T> trees) where T : class , ITreeNode<T> { List<T> treeNodeList = new List<T>(); foreach (T rootNode in trees) { foreach (T node in DepthFirstTraversal(rootNode)) { treeNodeList.Add(node); } } return treeNodeList; } #endregion #region Search methods /// <summary>Finds the TreeNode with the given Id in the given tree by searching the descendents. /// Returns null if the node cannot be found.</summary> public static T FindDescendant<T>( this T searchRoot, int id) where T : class , ITreeNode<T> { EnsureTreePopulated(searchRoot, "searchRoot" ); foreach (T child in DepthFirstTraversal(searchRoot)) { if (child.Id == id) { return child; } } return null ; } /// <summary>Finds the TreeNode with the given id from the given forest of trees. /// Returns null if the node cannot be found.</summary> public static T FindTreeNode<T>( this IEnumerable<T> trees, int id) where T : class , ITreeNode<T> { foreach (T rootNode in trees) { if (rootNode.Id == id) { return rootNode; } T descendant = FindDescendant(rootNode, id); if (descendant != null ) { return descendant; } } return null ; } #endregion #region Useful tree properties /// <summary> /// Checks whether there is a loop from the current node up the tree back to the current node. /// It is recommended that this is checked to be false before saving the node to your data store. /// </summary> /// <example> /// The most simple example of a hierarchy loop is were there are 2 nodes, "A" and "B", and "A" /// is "B"'s parent, and "B" is "A"'s parent. This is not allowed, and should not be saved. , /// </example> public static bool HasHeirachyLoop<T>( this T node) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); T tempParent = node.Parent; while (tempParent != null ) { if (tempParent.Id == node.Id) { return true ; } tempParent = tempParent.Parent; } return false ; } /// <summary>Returns the root node of the tree that the given TreeNode belongs in</summary> public static T GetRootNode<T>( this T node) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); T cur = node; while (cur.Parent != null ) { cur = cur.Parent; } return cur; } /// <summary> /// Gets the depth of a node, e.g. a root node has depth 0, its children have depth 1, etc. /// </summary> public static int GetDepth<T>( this T node) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); int depth = 0; while (node.Parent != null ) { ++depth; node = node.Parent; } return depth; } /// <summary> /// Gets the type of node that the specified node is. /// </summary> public static NodeType GetNodeType<T>( this T node) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); if (node.Parent == null ) { return NodeType.Root; } else if (node.Children.Count == 0) { return NodeType.Leaf; } return NodeType.Internal; } #endregion #region Iterators /// <summary> /// Returns an Iterator which starts at the given node, and climbs up the tree to /// the root node. /// </summary> /// <param name="startNode">The node to start iterating from. This will be the first node returned by the iterator.</param> public static IEnumerable<T> ClimbToRoot<T>( this T startNode) where T : class , ITreeNode<T> { EnsureTreePopulated(startNode, "startNode" ); T current = startNode; while (current != null ) { yield return current; current = current.Parent; } } /// <summary> /// Returns an Iterator which starts at the root node, and goes down the tree to /// the given node node. /// </summary> /// <param name="startNode">The node to start iterating from. This will be the first node returned by the iterator.</param> public static List<T> FromRootToNode<T>( this T node) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); List<T> nodeToRootList = new List<T>(); foreach (T n in ClimbToRoot(node)) { nodeToRootList.Add(n); } nodeToRootList.Reverse(); return nodeToRootList; } /// <summary> /// Returns an Iterator which starts at the given node, and traverses the tree in /// a depth-first search manner. /// </summary> /// <param name="startNode">The node to start iterating from. This will be the first node returned by the iterator.</param> public static IEnumerable<T> DepthFirstTraversal<T>( this T startNode) where T : class , ITreeNode<T> { EnsureTreePopulated(startNode, "node" ); yield return startNode; foreach (T child in startNode.Children) { foreach (T grandChild in DepthFirstTraversal(child)) { yield return grandChild; } } } /// <summary> /// Returns an Iterator which traverses a forest of trees in a depth-first manner. /// </summary> /// <param name="trees">The forest of trees to traverse.</param> public static IEnumerable<T> DepthFirstTraversalOfList<T>( this IEnumerable<T> trees) where T : class , ITreeNode<T> { foreach (T rootNode in trees) { foreach (T node in DepthFirstTraversal(rootNode)) { yield return node; } } } /// <summary> /// Gets the siblings of the given node. Note that the given node is included in the /// returned list. Throws an <see cref="Exception" /> if this is a root node. /// </summary> /// <param name="node">The node whose siblings are to be returned.</param> /// <param name="includeGivenNode">If false, then the supplied node will not be returned in the sibling list.</param> public static IEnumerable<T> Siblings<T>( this T node, bool includeGivenNode) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); if (GetNodeType(node) == NodeType.Root) { if (includeGivenNode) { yield return node; } yield break ; } foreach (T sibling in node.Parent.Children) { if (!includeGivenNode && sibling.Id == node.Id) { // current node is supplied node; don't return it unless it was asked for. continue ; } yield return sibling; } } /// <summary> /// Traverses the tree in a breadth-first fashion. /// </summary> /// <param name="node">The node to start at.</param> /// <param name="returnRootNode">If true, the given node will be returned; if false, traversal starts at the node's children.</param> public static IEnumerable<T> BreadthFirstTraversal<T>( this T node, bool returnRootNode) where T : class , ITreeNode<T> { EnsureTreePopulated(node, "node" ); if (returnRootNode) { yield return node; } foreach (T child in node.Children) { yield return child; } foreach (T child in node.Children) { foreach (T grandChild in BreadthFirstTraversal(child, false )) { yield return grandChild; } } } #endregion #region Private methods [System.Diagnostics.Conditional( "DEBUG" )] private static void EnsureTreePopulated<T>(T node, string parameterName) where T : class , ITreeNode<T> { if (node == null ) { throw new ArgumentNullException(parameterName, "The given node cannot be null." ); } if (node.Children == null ) { throw new ArgumentException( "The children of " + parameterName + " is null. Have you populated the tree fully by calling TreeHelper<T>.ConvertToForest(IEnumerable<T> flatNodeList)?" , parameterName); } } #endregion } /// <summary> /// A type of tree node. /// </summary> public enum NodeType { /// <summary> /// A node which is at the root of the tree, i.e. it has no parents. /// </summary> Root, /// <summary> /// A node which has parent and children. /// </summary> Internal, /// <summary> /// A node with no children. /// </summary> Leaf } } |
from : https://www.codeproject.com/articles/23949/building-trees-from-lists-in-net
sql:
1 2 3 4 5 6 7 8 9 10 | CREATE TABLE Category ( Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL , [ Name ] NVARCHAR(20) not NULL , ParentID INT ) GO SELECT Id, [ Name ], ParentID FROM Category |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | public class Category { private int _id; private string _name; private Category _parent; private List<Category> _children; public int Id { get { return _id; } set { _id = value; } } public string Name { get { return _name; } set { _name = value; } } public Category Parent { get { return _parent; } set { _parent = value; } } public List<Category> Children { get { return _children; } set { _children = value; } } } static List<Category> GetListFromDatabase(DbConnection con) { DbCommand cmd = con.CreateCommand(); cmd.CommandText = "SELECT Id, Name, ParentID FROM Category" ; cmd.CommandType = CommandType.Text; DbDataReader reader = cmd.ExecuteReader(); List<Category> categories = new List<Category>(); foreach (DbDataRecord row in reader) { Category c = new Category(); c.Id = ( int )row[ "Id" ]; c.Name = ( string )row[ "Name" ]; if (row[ "ParentID" ] != DBNull.Value) { c.Parent = new Category(); c.Parent.Id = ( int )row[ "ParentID" ]; } categories.Add(c); } reader.Close(); return categories; } public class Category : ITreeNode<Category> { // contents of class remain as above, because the // interface is implemented by the Id, Parent, and // Children properties } IList<Category> topLevelCategories = TreeHelper.ConvertToForest(GetListFromDatabase()); void Page_Load( object sender, EventArgs e) { IList<Category> topLevelCategories = TreeHelper.ConvertToForest(Category.GetListFromDatabase()); Response.Write( "<ul>" ); foreach (Category topLevelCategory in topLevelCategories) { RenderCategory(topLevelCategory); } Response.Write( "</ul>" ); } void RenderCategory(Category category) { Response.Write( "<li>" + category.Name); if (category.Children.Count > 0) { Response.Write( "<ul>" ); foreach (Category child in category.Children) { RenderCategory(child); } Response.Write( "</ul>" ); } Response.Write( "</li>" ); } // in a website, this may use the ASP.NET Cache object. List<Category> categories = GetCategories(); int categoryId = int .Parse(Request.Params[ "categoryId" ]); Category currentCategory = TreeHelper.FindTreeNode(categories, categoryId); Category currentCategory = GetCategory(); foreach (Category category in TreeHelper.Iterators.FromRootToNode(currentCategory)) { Response.Write( " / " + category.Name); } List<Category> categories = GetCategories().ConvertToForest(); Category current = categories.FindCategory(3); foreach (Category descendent in current.DepthFirstTraversal()) { Response.Write( "Depth of " + descendent.Name + ": " + descendent.GetDepth(); } List<Category> categoryList = Category.GetCategories(); // Get all categories which are not top level categories, // and retrieve only the name. var nonRootCategories = from c in categoryList.DepthFirstTraversalOfList() where c.Parent != null select new { Name = c.Name }; // Get all categories at Depth 2, ordered by name, and // get the whole category object. var level2Categories = from c in categoryList.DepthFirstTraversalOfList() where c.GetDepth() == 2 orderby c.Name ascending select c; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | /// <summary> /// Geovin Du /// 涂聚文 /// </summary> public partial class WebForm11 : System.Web.UI.Page { int cc = 0; int nn = 0; CategoryBLL bll = new CategoryBLL(); /// <summary> /// 排序和頁碼設定 /// 塗聚文 /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load( object sender, EventArgs e) { int projectid = 1; DataTable table = bll.GetList(projectid).Tables[0]; DataRow[] parentMenus = table.Select( "ParentId is null" , "IdOrder asc" ); StringBuilder sb = new StringBuilder(); string unorderedList = GenerateUL(parentMenus, table, sb); // Response.Write(unorderedList); this .geovindu.InnerHtml = unorderedList; //IList<Category> topLevelCategories = TreeHelper.ConvertToForest(list); //Response.Write("<ul>"); //foreach (Category topLevelCategory in topLevelCategories) //{ // RenderCategory(topLevelCategory); //} //Response.Write("</ul>"); } /// <summary> /// /// </summary> /// <param name="menu"></param> /// <param name="table"></param> /// <param name="sb"></param> /// <returns></returns> private string GenerateUL(DataRow[] menu, DataTable table, StringBuilder sb) { sb.AppendLine( "<ul>" ); int dispage = table.Rows.Count; nn = 0; string line = string .Empty; if (menu.Length > 0) { foreach (DataRow dr in menu) { //Dim handler As String = dr("Handler").ToString() string menuText = dr[ "CategoryName" ].ToString().Trim(); string page = dr[ "Id" ].ToString(); int pageset = ( int )dr[ "PageSet" ]; int strlen =menuText.Length*3; if ((cc) == 0) { string dd = menuText.PadRight(70 - strlen, '.' ); line = String.Format( "<li><a href='#book1/{0}'>{1}</a>" , pageset, dd); } else { string ss = pageset.ToString().PadLeft(2, '0' ); string dd = menuText.PadRight(70 - strlen, '.' ); // strlen = dd.Length; line = String.Format( "<li><a href='#book1/{0}'>{1}第{2}頁</a>" , pageset, dd, ss,dd.Length-strlen+ "," +strlen.ToString()); } sb.Append(line); string pid = dr[ "Id" ].ToString(); DataRow[] subMenu = table.Select(String.Format( "ParentId = {0}" , pid), "IdOrder asc" ); if (subMenu.Length > 0) { StringBuilder subMenuBuilder = new StringBuilder(); if (nn == 1) cc--; else cc++; nn++; //Response.Write("内二层:"+cc.ToString()+"n:"+nn.ToString()+menuText+"<br/>"); sb.Append(GenerateUL(subMenu, table, subMenuBuilder)); } cc++; sb.Append( "</li>" ); //Response.Write("一层:" + cc.ToString() + menuText + "<br/>"); } } sb.Append( "</ul>" ); // Response.Write("外一层:" + cc.ToString() + "<br/>"); return sb.ToString(); } /// <summary> /// /// </summary> /// <param name="category"></param> void RenderCategory(Category category) { Response.Write( "<li>" + category.Name); if (category.Children.Count > 0) { Response.Write( "<ul>" ); foreach (Category child in category.Children) { RenderCategory(child); } Response.Write( "</ul>" ); } Response.Write( "</li>" ); } } |
https://forums.asp.net/t/1821996.aspx
https://www.c-sharpcorner.com/UploadFile/rohatash/creating-dynamic-menu-from-database-sql-server-in-Asp-Net/
https://stackoverflow.com/questions/14137811/generate-nested-menu-from-datatable-using-c-sharp-as-ul-list-not-asp-net-menu-co
https://www.codeproject.com/questions/739219/how-to-create-ul-li-dynamically-from-database-usin
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!