0

I have a nested menu - here a simplified class:

public class NestedNode
{
    public string Url { get; set; }
    public List<NestedNode> Children { get; set; }
}

Given that I have a recursive list of NestedNode, I'm trying to ascertain whether any descendant is active at any level.

Here's the code to test:

protected void Page_Load(object sender, EventArgs e)
{
    // The url of the current page
    var currentUrl = Request.Url.GetLeftPart(UriPartial.Path);

    // This is a list of nested nodes
    var nodes = SiloNodes;

    // Start loop
    RecursiveCall(nodes, currentUrl);
}

void RecursiveCall(IEnumerable<NestedNode> nodes, string currentUrl)
{
    if (nodes == null) return;

    foreach (var n in nodes)
    {
            // This can test current level only
            //var isActive = n.Url == currentUrl;

            // This can test next level down
            //var isActive = n.Children.Any(c => c.Url == currentUrl);

            // How can I test all levels in one go?

            RecursiveCall(n.Children, currentUrl);
    }
}

What I need to be able to do is work out if any of the parents children are active (at the top lavel) so that I can add classes. At the moment, my ideas only go one level deep.

2
  • So RecursiveCall is not performing as expected on the child lists below the first level? Commented Oct 23, 2018 at 15:09
  • Well it is, but that's not the problem. When I enter the foreach, I traverse 0 or more levels of children. What I need to know is if any of those children are the current page. Obviously, I can test that on a node by node basis, but I need to know if any child (n) levels down is the current page, and flag it at the top level.
    – John Ohara
    Commented Oct 23, 2018 at 15:21

2 Answers 2

1

How about something like

void Main()
{
    var nodes = new List<NestedNode>();

    var isActive = nodes.Any(n => n.AnyActive("url"));
}

public class NestedNode
{
    public NestedNode()
    {
        Children = Enumerable.Empty<NestedNode>();
    }
    public string Url { get; set; }
    public IEnumerable<NestedNode> Children { get; set; }

    public bool AnyActive(string url){ return Url==url || Children.Any(c => c.AnyActive(url));}
}
1
  • I like the use of the short-circuit ||. Should have thought about that myself :-) Commented Oct 23, 2018 at 15:17
0

In this situation I would probably add a method to the NestedNode to check the condition recursively - something like this:

public bool ExistsRecursive(Func<NestedNode, bool> predicate)
{
    if(predicate(this))
    {
        return true;
    }
    foreach(var node in Children)
    {
        return predicate(node);
    }
    return false;
}

And then, in your Page_Load, all you need is this:

if(nodes.ExistsRecursive(n => n.Url == currentUrl))
{
    // current url is found in at least one node
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.