Nerd Power

The World Runs on Nerds

Visual Studio Macro: Collapse Solution Explorer and Close All Documents

Developers working with Visual Studio on a project of significant size understand how cluttered the Solution Explorer becomes after a few hours of working. They click too many of those little minus signs — a repetitive task that no developer enjoys. Eventually they decide to ease their discomfort and search Google for a better solution. Luckily, a number of individuals have posted solutions for this task, gracefully solving the problem by creating macros assigned to specific key strokes.

Searching Google for ‘collapse solution explorer’ reveals many, many solutions. I found that two basic macros exist: 1) a quick collapse and 2) complete collapse. The quick version collapses all currently open nodes in the solution tree. The process is fast (2-ish seconds) and the screen looks nice and organized.

There is one problem with the quick collapse which leaves trouble lurking. If nodes of the tree were expanded but then hidden by collapsing the parent node, those expanded nodes further down the tree structure will not be collapsed. This occurs because the macro only collapses the children of a node if the parent node is expanded.

This problem with quick collapse is addressed by the second macro: complete collapse. The complete collapse iterates through the entire tree regardless of the parent node’s expanded/collapsed status. This forces every node of the tree to be collapsed. It is a thorough process and guarantees that the solution explorer will be in perfect order however, it is a lengthy process for projects of significant size (15-ish seconds).

The code I provide below combines these two macros into one module. You can assign each a separate keystroke and have the power of both at your fingertips. Use the quick collapse as everyday cleanup; use the complete collapse for those times when the solution explorer has become unruly.

I also added a bit of functionality to the quick collapse. I usually collapse the solution explorer because I want to declutter my work space before diving into a task. That often means that I have a number of files open that I am no longer working on. To address this, I provide two additional macros that will close all open files before executing the quick collapse. The first macro closes all files except the active window. The second macro closes all files including the active window. The files are automatically saved before closing.

Using Tools > Options > Environment > Keyboard, you can assign each macro a keyboard shortcut. I prefer the following:

Shortcut Key Macro Assigned
Alt+\ Quick Collapse
Ctrl+Alt+\ Complete Collapse
Alt+/ Quick Collapse – close all documents except active
Ctrl+Alt+/ Quick Collapse – close all documents including active

Here is a link to step-by-step instructions for creating macros and setting the keyboard shortcuts. Here is a link to step-by-step instructions for adding macros as a toolbar button.

The Macros

Download the CollapseSolutionExplorer macro file here or copy and paste from below.


Imports EnvDTE
Imports System.Diagnostics

Public Module CollapseSolutionExplorer

    Sub QuickCollapseAndClose()
        CloseAllWindows(False)
        DoCollapse(True)
    End Sub

    Sub QuickCollapseAndCloseKeepActive()
        CloseAllWindows(True)
        DoCollapse(True)
    End Sub

    Sub QuickCollapse()
        DoCollapse(True)
    End Sub

    Sub CompleteCollapse()
        DoCollapse(False)
    End Sub

    Private Sub DoCollapse(ByVal quick As Boolean)

        ' Get the the Solution Explorer tree
        Dim UIHSolutionExplorer As UIHierarchy
        UIHSolutionExplorer = DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Object()

        ' Check if there is an open solution
        If (UIHSolutionExplorer.UIHierarchyItems.Count = 0) Then
            Return
        End If

        ' Get the top node (the name of the solution)
        Dim UIHSolutionRootNode As UIHierarchyItem
        UIHSolutionRootNode = UIHSolutionExplorer.UIHierarchyItems.Item(1)

        ' Hide the Solution Explorer to prevent multiple screen paints
        DTE.StatusBar.Text = "Solution Explorer hidden... it will return..."
        Dim activeWindow As EnvDTE.Window
        activeWindow = UIHSolutionExplorer.DTE.ActiveWindow
        DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Visible = False

        ' Select the solution (top) node so that the open document isn't automatically expanded
        UIHSolutionRootNode.Select(vsUISelectionType.vsUISelectionTypeSelect)

        ' Collapse each project node
        Dim UIHItem As UIHierarchyItem
        For Each UIHItem In UIHSolutionRootNode.UIHierarchyItems
            ' the first-level is always collapsed, regardless of quick or not
            ' this is a nice feature that makes the quick collapse more useful
            Collapse(UIHItem, quick)
        Next

        ' Bring back the Solution Explorer
        DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Visible = True

        ' Clear the status bar
        DTE.StatusBar.Clear()
        DTE.StatusBar.Progress(False)

    End Sub

    Private Sub Collapse(ByVal item As UIHierarchyItem, ByVal quick As Boolean)

        'recursive function

        For Each eitem As UIHierarchyItem In item.UIHierarchyItems
            If ((quick = True) And (eitem.UIHierarchyItems.Expanded = True)) Or (quick = False) Then
                If eitem.UIHierarchyItems.Count > 0 Then
                    DTE.StatusBar.Text = "Solution Explorer hidden... it will return... Collapsing " & item.Name
                    Collapse(eitem, quick) ' recursion here
                End If
            End If
        Next

        item.UIHierarchyItems.Expanded = False

    End Sub

    Private Sub CloseAllWindows(ByVal KeepCurrentOpen As Boolean)

        On Error Resume Next

        Dim i As Integer
        Dim sCurrWin As String = DTE.ActiveDocument.Name

        With DTE
            For i = .Documents.Count To 1 Step -1
                If .Documents.Item(i).Name <> sCurrWin Or KeepCurrentOpen = False Then
                    .Documents.Item(i).Close(vsSaveChanges.vsSaveChangesYes)
                End If
            Next
        End With

    End Sub

End Module

Your email address will not be published. Required fields are marked *

*