C# 在C中使用父对象和子对象迭代保存分层(Treeview)对象#

C# 在C中使用父对象和子对象迭代保存分层(Treeview)对象#,c#,C#,我有一个数据库表对象,它是: [Table("TreeViewDb")] public class TreeViewDb { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public int ParentId { get; set; } public string Name { get; set; }

我有一个数据库表对象,它是:

[Table("TreeViewDb")]
public class TreeViewDb
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }    
}
我有一个视图模型,它是:

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

    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }

    // children
    public List<TreeView> Children { get; set; }
}
好了:

  • 使用
    堆栈
    包括项目深度
  • 按顺序迭代节点
  • 决定是否保存它

代码:

使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
名称空间zzzzzz
{
内部静态类程序
{
私有静态void Main(字符串[]args)
{
变量节点=新节点(“节点0@级别0”)
{
新节点(“节点1@级别1”)
{
新节点(“节点2@级别2”)
{
新节点(“节点3@级别3”)
{
新节点(“节点4@级别4”)
}
}
},
新节点(“节点5@级别1”)
{
新节点(“节点6@级别2”)
{
新节点(“节点7@级别3”)
}
}
};
var stack=新堆栈();
stack.Push((节点,0));
while(stack.Any())
{
var(当前,深度)=stack.Pop();
ProcessNode(当前、深度);
foreach(current.Reverse()中的变量项)
{
堆栈推送((项目,深度+1));
}
}
}
私有静态void ProcessNode(节点节点,int-depth)
{
Write($“{newstring('\t',depth)}{node}”);
var color=Console.ForegroundColor;
Console.ForegroundColor=深度<3?ConsoleColor.绿色:ConsoleColor.红色;
Write($“{(深度<3?”已保存):“已忽略”)}{Environment.NewLine});
Console.ForegroundColor=颜色;
}
}
公共类节点:IList
{
公共节点(字符串文本)
{
文本=文本;
}
公共字符串文本{get;set;}
私有IList列表{get;}=new List();
公共IEnumerator GetEnumerator()
{
返回List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return((IEnumerable)List).GetEnumerator();
}
公共作废添加(节点项)
{
列表。添加(项目);
}
公共空间清除()
{
List.Clear();
}
公共布尔包含(节点项)
{
返回列表。包含(项目);
}
public void CopyTo(节点[]数组,int arrayIndex)
{
CopyTo(数组,arrayIndex);
}
公共布尔删除(节点项)
{
退货清单。删除(项目);
}
public int Count=>List.Count;
public bool IsReadOnly=>List.IsReadOnly;
public int IndexOf(节点项)
{
返回列表。索引(项目);
}
公共void插入(整数索引,节点项)
{
列表。插入(索引,项目);
}
公共无效删除(整数索引)
{
列表。删除(索引);
}
公共节点此[int索引]
{
get=>List[index];
set=>List[index]=值;
}
公共重写字符串ToString()
{
返回$“{nameof(Text)}:{Text}”;
}
}
}
好了:

  • 使用
    堆栈
    包括项目深度
  • 按顺序迭代节点
  • 决定是否保存它

代码:

使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
名称空间zzzzzz
{
内部静态类程序
{
私有静态void Main(字符串[]args)
{
变量节点=新节点(“节点0@级别0”)
{
新节点(“节点1@级别1”)
{
新节点(“节点2@级别2”)
{
新节点(“节点3@级别3”)
{
新节点(“节点4@级别4”)
}
}
},
新节点(“节点5@级别1”)
{
新节点(“节点6@级别2”)
{
新节点(“节点7@级别3”)
}
}
};
var stack=新堆栈();
stack.Push((节点,0));
while(stack.Any())
{
var(当前,深度)=stack.Pop();
ProcessNode(当前、深度);
foreach(current.Reverse()中的变量项)
{
堆栈推送((项目,深度+1));
}
}
}
私有静态void ProcessNode(节点节点,int-depth)
{
Write($“{newstring('\t',depth)}{node}”);
var color=Console.ForegroundColor;
Console.ForegroundColor=深度<3?ConsoleColor.绿色:ConsoleColor.红色;
Write($“{(深度<3?”已保存):“已忽略”)}{Environment.NewLine});
Console.ForegroundColor=颜色;
}
}
公共类节点:IList
{
公共节点(字符串文本)
{
文本=文本;
}
公共字符串文本{get;set;}
私有IList列表{get;}=new List();
公共IEnumerator GetEnumerator()
{
返回List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return((IEnumerable)List).GetEnumerator();
}
公共作废添加(节点项)
{
列表。添加(项目);
}
公共空间清除()
{
List.Clear();
}
酒吧
public bool SaveOrUpdateTreeView(TreeView viewModel)
{
    // Level 1
    var parentModel = new TreeViewDb
    {
        Id = viewModel.Id,
        ParentId = viewModel.ParentId,
        Name = viewModel.Name
    };

    // Save or update object and return primary key
    var parentId = _dataRepository.SaveOrUpdateTreeView(parentModel);

    // Level 2
    foreach (var child in viewModel.Children)
    {
        var childModel = new TreeViewDb
        {
            Id = viewModel.Id,
            ParentId = parentId, // Parent Primary Key
            Name = viewModel.Name
        };

        // Save or update object and return primary key
        var childId = _dataRepository.SaveOrUpdateTreeView(childModel);

        // Level 3
        foreach (var grandChild in child.Children)
        {
            var grandChildModel = new TreeViewDb
            {
                Id = viewModel.Id,
                ParentId = childId, // Child Primary Key
                Name = viewModel.Name
            };

            _dataRepository.SaveOrUpdateTreeView(grandChildModel);
        }
    }

    return true;
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace zzzzzzzz
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var node = new Node("node 0 @ level 0")
            {
                new Node("node 1 @ level 1")
                {
                    new Node("node 2 @ level 2")
                    {
                        new Node("node 3 @ level 3")
                        {
                            new Node("node 4 @ level 4")
                        }
                    }
                },
                new Node("node 5 @ level 1")
                {
                    new Node("node 6 @ level 2")
                    {
                        new Node("node 7 @ level 3")
                    }
                }
            };


            var stack = new Stack<(Node, int)>();

            stack.Push((node, 0));

            while (stack.Any())
            {
                var (current, depth) = stack.Pop();

                ProcessNode(current, depth);

                foreach (var item in current.Reverse())
                {
                    stack.Push((item, depth + 1));
                }
            }
        }

        private static void ProcessNode(Node node, int depth)
        {
            Console.Write($"{new string('\t', depth)}{node}");
            var color = Console.ForegroundColor;
            Console.ForegroundColor = depth < 3 ? ConsoleColor.Green : ConsoleColor.Red;
            Console.Write($" {(depth < 3 ? "SAVED" : "IGNORED")}{Environment.NewLine}");
            Console.ForegroundColor = color;
        }
    }

    public class Node : IList<Node>
    {
        public Node(string text)
        {
            Text = text;
        }

        public string Text { get; set; }

        private IList<Node> List { get; } = new List<Node>();

        public IEnumerator<Node> GetEnumerator()
        {
            return List.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable) List).GetEnumerator();
        }

        public void Add(Node item)
        {
            List.Add(item);
        }

        public void Clear()
        {
            List.Clear();
        }

        public bool Contains(Node item)
        {
            return List.Contains(item);
        }

        public void CopyTo(Node[] array, int arrayIndex)
        {
            List.CopyTo(array, arrayIndex);
        }

        public bool Remove(Node item)
        {
            return List.Remove(item);
        }

        public int Count => List.Count;

        public bool IsReadOnly => List.IsReadOnly;

        public int IndexOf(Node item)
        {
            return List.IndexOf(item);
        }

        public void Insert(int index, Node item)
        {
            List.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            List.RemoveAt(index);
        }

        public Node this[int index]
        {
            get => List[index];
            set => List[index] = value;
        }

        public override string ToString()
        {
            return $"{nameof(Text)}: {Text}";
        }
    }
}
    public static IEnumerable<(T Parent, T Node, int Level)> BreadthFirst<T>(T self, Func<T, IEnumerable<T>> selector)
    {
        var queue = new Queue<(T Parent, T Node, int Level)>();
        queue.Enqueue((self, self, 0));
        while (queue.Count > 0)
        {
            var current = queue.Dequeue();
            yield return current;
            var node = current.Node;
            var level = current.Level + 1;
            foreach (var child in selector(node))
            {
                queue.Enqueue((node, child, level));
            }
        }
    }
var nodes = BreadthFirst(viewModel, v => v.Children).Where(t => t.Level < 3);