There was a recent post in the Visual C# IDE forum which started me thinking about navigating through a solution in Visual Studio. The post was basically asking whether it’s possible to quickly navigate to a file in your solution if you know its name. There are a few different navigational approaches that Visual Studio offers. First, if the file is already open, then it’s possible to use Ctrl+Tab or the tab channel to find the file. Ctrl+Tab functionality was actually significantly improved in VS 2005. In VS 2003 Ctrl-Tab had no UI associated with it, so it was difficult to navigate to a particular open file (though it was extremely good at quickly switching between 2 or 3 files). In VS 2005 Ctrl+Tab now shows UI that enables navigation to both open files and active tool windows. The UI is modeled after the Alt-Tab functionality in Windows:
It’s not immediately obvious the first time that the Ctrl+Tab feature is used that the arrow keys can be used to navigate among the items. For example, invoke the window by typing Ctrl+Tab. Keep the Ctrl key depressed, but release the Tab key. Now simply use the arrow keys on the keyboard to change the selection to either the file or tool window that should acquire focus.
Another option to quickly navigate to open files is the use of the file tab channel. The tab channel (the list of tabs that contain the name of the documents that are open if ‘tabbed documents’ is the current mode) also underwent an overhaul in VS 2005. The mouse is an obvious way to navigate using the channel, but there is a more keyboard focused route as well. The channel has a little chevron on the right hand side which when clicked will show a drop-down of all open documents (regardless of whether they are visible in the tab channel). This shortcut can be invoked via Ctrl+Alt+<Down Arrow>. A small drop-down appears and has focus; the arrow keys can be used to quickly select the file to make active:
The final tried and true mechanism that I’ll talk about for accessing open documents is the Windows ‘window’. It’s accessible off of the Window top level menu item (Alt-W, W). This particular navigation mechanism is useful to know because it works the same in VS 2003 and VS 2005, and it works regardless of whether environment is set to ‘tabbed documents’ or ‘multiple documents’. The accelerator key for activating the selection is “Alt+A” when the window has focus:
Of course, none of those navigation methods works if the desired file isn’t already open in the editor. There are several different ways to navigate to open a file, but the most common is probably Solution Explorer. In fact, the question referenced above was specifically about finding a way to navigate solution explorer via the keyboard (quickly) even in the face of collapsed nodes. It turns out that there really isn’t a good way to do this. However, there are a few other options for opening files that are in the solution. For example, it’s possible to quickly open a file in the solution using the find combo box that appears on the Standard toolbar. The keybinding to jump to the combo box is Ctrl+/ with the C# keybindings. Invoke this keybinding, and then type “>” to enter ‘command’ mode. Type the word ‘open’ and then start to type the name of a file in the solution. A list of files, filtered by the text already typed, appears as a dropdown:
The biggest problem with this approach is that selecting an item in the list immediately puts the full path name of that item into the combobox, which after another character is typed (like backspace) will filter the list down to only files with that path. A smaller issue is that the list also contains various other solution artifacts like the references, so the list is longer than it needs to be. The nail in the coffin for me is that it doesn’t filter based on substrings anywhere in the filename, but rather only what the filename starts with. That is, searching for Item wouldn’t return “IconicItem.cs.”
I’ve often found myself wanting a way to quickly navigate to a file that meets the following requirements:
· A modal UI that disappears as soon as I’m done using it
· A filtered list of only the files that are in my solution
· A way to quickly search through those files using a substring search
· Keyboard focused access such that I don’t need to use the mouse at all
It turns out that Visual Studio doesn’t have a tool or feature that meets all of these criteria by default. There are many that come close, like the Find Combo above, or Open File (Ctrl+O). Unfortunately none of them is exactly what I want. Luckily it’s possible to extend VS with some interesting addins. In this case I wrote a simple little navigation tool that has the following UI:
The Matching Files listbox contains all of the files in the solution, regardless of their project (or their type, notice NavigationForm.resX). The Project listbox is contextual based on the selection in the Matching Files listbox. In this case AssemblyInfo.cs occurs in the NavigationUI, FileNavigationAddin, and TypeNavigationAddIn projects. The ‘Select a file to Open’ textbox filters the list of Matching Files down based on a substring match. The up and down arrows will change the selection in the Matching Files listbox even while the ‘Select a file to open’ textbox has focus; similarly, the Shift+ the up or down arrows will change the selection in the Project listbox.
The addin works fairly well for small to medium solutions, but it takes time to appear in the face of larger solutions. Currently it enumerates the files in every project in the solution every time it is invoked. To make it faster would require keeping track of a list of files and updating them based on project events like additions, removals and renames, which I haven’t been motivated to do yet.
Regardless, the file navigation addin is available here in .vsi form. After running the VSI a new command named FileNavigationAddin.Connection.Connect.FileNavigationAddIn is added to Visual Studio. There is no default keybinding, so one must be set through the Tools | Options | Keyboard page. I override Ctrl+T because I never use Edit.TransposeCharacter.