从分层集合中删除对象

Cod*_*ire 3 c# linq

我在分层列表中有一组NodeObject类.列表可以是任意数量的级别.

public class NodeModel : ViewModelBase
{
    public Guid Id { get; set; }
    public string Caption { get; set; }
    public string Description { get; set; }
    public NodeType Type { get; set; }
    public List<NodeModel> Children { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如何使用其Guid Id从列表中删除项目,无论它在列表中的哪个位置?

Mic*_*ing 10

这是一种递归方式:

private void DeleteNode(IList<Node> nodes, Guid id)
{
    Node nodeToDelete = null;
    foreach (var node in nodes)
    {
        if (node.Id == id)
        {
            nodeToDelete = node;
            break;
        }
        DeleteNode(node.Children, id);
    }
    if (nodeToDelete != null)
    {
        nodes.Remove(nodeToDelete);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想在一个循环中完成所有操作,请使用for循环执行此操作.但在我看来,阅读起来要困难得多.

private void DeleteNode(IList<Node> nodes, int id)
{
    for (var index = 0; index < nodes.Count; index++)
    {
        var currentNode = nodes[index];
        if (currentNode.Id == id)
        {
            nodes.Remove(currentNode);
            break;
        }
        DeleteNode(currentNode.Children, id);
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是拥有一个扁平(非分层)列表甚至字典(最快的方式!),它包含所有元素.您可以添加另一个属性,其中包含子项的父ID.在某些情况下,特别是当您拥有包含大量物品的深树时,这种方式会更加高效.如果要删除某个项目,请执行以下操作:

private void DeleteNode(IList<Node> flatNodes, Guid id)
{
    var nodeToDelete = flatNodes.FirstOrDefault(n => n.Id == id);
    if (nodeToDelete != null)
    {
        var parent = flatNodes.First(n => n.Id == nodeToDelete.ParentId);
        parent.Children.Remove(nodeToDelete);
    }
}

private void DeleteNodeFromFlatDictionary(IDictionary<Guid, Node> flatNodes, Guid id)
{
    if (!flatNodes.ContainsKey(id)) return;
    var nodeToDelete = flatNodes[id];
    parent[nodeToDelete.ParentId].Children.Remove(id);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您希望UI识别您需要使用的更改ObservableCollection<Node>.