private void CreateActionNodesRecursive(ref HierarchyNode <string, object> _parentNode, ref VisualiserBaseNode _parentVisualiserNode) { for (int i = 0; i < _parentNode.GetChildCount(); ++i) { var hierarchyNode = _parentNode.GetChildren()[i]; VisualiserBaseNode visualiserNode = new ActionNode(hierarchyNode, _weight: hierarchyNode.IsPartOfFoundPath() ? 1.0f : 0.0f); _parentVisualiserNode.AddChild(visualiserNode); CreateActionNodesRecursive(ref hierarchyNode, ref visualiserNode); } }
/// <summary> /// Enumerates over the hierarchy items for the given hierarchy traversing into nested hierarchies. /// </summary> /// <param name="hierarchy">hierarchy to enumerate over.</param> /// <param name="itemid">item id of the hierarchy</param> /// <param name="recursionLevel">Depth of recursion. e.g. if recursion started with the Solution /// node, then : Level 0 -- Solution node, Level 1 -- children of Solution, etc.</param> /// <param name="visibleNodesOnly">true if only nodes visible in the Solution Explorer should /// be traversed. false if all project items should be traversed.</param> private void VisitHierarchyNodes(HierarchyNode node, int recursionLevel, bool visibleNodesOnly) { // Note: This code originated from "Solution Hierarchy Traversal Sample (C#)" // https://msdn.microsoft.com/en-us/library/bb165347(v=vs.80).aspx // In C:\Setups\Microsoft\Visual Studio\VS 2005\Visual Studio 2005 SDK\ ... // VisualStudioIntegration\Samples\Project\CSharp\Example.SolutionHierarchyTraversal // // Check first if this node has a nested hierarchy. If so, then there really are two // identities for this node: 1. hierarchy/itemid and 2. nestedHierarchy/nestedItemId. // We will recurse and call VisitHierarchyNodes which will traverse this node using // the inner nestedHierarchy/nestedItemId identity. Basically, if this returns a // nested hierarchy, then the current node is just a shortcut to the nested hierarchy. HierarchyNode nestedNode; if (node.TryGetNestedHierarchy(out nestedNode)) { this.VisitHierarchyNodes(nestedNode, recursionLevel, visibleNodesOnly); } else { // In VS 2015 and earlier, the Solution node enumerates ALL projects (including nested projects) // when asking for FirstChild/NextSibling, but it doesn't do that for FirstVisibleChild/NextVisibleSibling. // VS treats the actual hierarchy differently than the visible hierarchy, and the solution contains // shortcuts to all the projects in the actual hierarchy. So if we're not restricted to visible nodes, // then we can encounter nested projects twice as we traverse the hierarchy. We'll make sure // we don't traverse through the same project twice. However, we can't restrict to visible items // because we need to ensure that we get the "Miscellaneous Files" (e.g., external files opened // in the solution), which may not be visible in the Solution Explorer. // // Note: currentItem can be null if we're visiting a physical folder (e.g., a Properties folder), a // virtual folder (e.g., Solution Items or Miscellaneous Files), or some other node type that is // not a solution, project or file type. HierarchyItem currentItem = this.VisitHierarchyNode(node); bool visitChildren = true; if (currentItem != null) { visitChildren = currentItem.ItemType != HierarchyItemType.Project || !this.visitedProjects.Contains(currentItem.FileName); if (visitChildren) { this.items.Add(currentItem); } } if (visitChildren) { // Note: We'll push a null parent for miscellaneous files since they're not directly referenced by the solution. bool pushCurrentItemAsAncestor = (currentItem != null && currentItem.IsContainer) || (currentItem == null && node.ItemType == VSConstants.GUID_ItemType_VirtualFolder && node.CanonicalName == "Miscellaneous Files"); if (pushCurrentItemAsAncestor) { this.ancestors.Push(currentItem); } try { recursionLevel++; List <HierarchyNode> children = node.GetChildren(visibleNodesOnly).ToList(); foreach (HierarchyNode child in children) { this.VisitHierarchyNodes(child, recursionLevel, visibleNodesOnly); } } finally { if (pushCurrentItemAsAncestor) { this.ancestors.Pop(); } } if (currentItem != null && currentItem.ItemType == HierarchyItemType.Project) { this.visitedProjects.Add(currentItem.FileName); } } } }