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

posted @   ®Geovin Du Dream Park™  阅读(110)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示