Click here to Skip to main content
Click here to Skip to main content

GoToFile Add In - Navigate Large Visual Studio Solutions Quickly

, 20 Mar 2009
Rate this:
Please Sign up or sign in to vote.
A Visual Studio Add In that quickly takes you to your desired file with few keyboard hits. Alt + G to list files in solution.

Introduction 

Visual Studio users spend lots of time navigating, moving from one file to another using solution explorer. GoToFile is a Visual Studio Add In that quickly takes you to your desired file with few keyboard hits.

Background  

Now a days, an average Visual Studio solutions has 100s and sometimes 1000s of files. I recently did some projects that contain more than 1000 files. Navigating from file to file using a solution explorer takes lots of effort. To open a file, you have to go from project to folder to many sub-folders and then a file. Sometimes you don't remember the folder where the file is.

Besides that, a few weeks ago, I used IntelliJ Idea IDE for Java development and it has this feature similar to GotToFile. So from there, I got the idea of having this Add In for Visual Studio that takes you to your desired file with just a few keyboard hits.

Using the Add In

This Add In is pretty straight forward. When you press Alt + G, a dialog with one text box pops up. As you type in the file name in the text box, a list of matched files in your solution is displayed. You could hit enter to open a file or press up and down arrow keys to move within a list. Following is a keyboard help: 

  1. Alt + G = Open GoToFile
  2. Esc = Close GoToFile
  3. Enter = Goto selected file
  4. Up, Down Arrow & Tab = Move between file list and file filter text box
  5. * = Wild card (e.g. *.gif, *.cs)
  6. Ctrl + F = Toggle show all matched files. Default is 99 files

Using the Code

The Add In mainly consists of a Connect.cs class and MainForm. Connect.cs is created when you create a new Add In project. MainForm is the main dialog of GoToFile. MainForm is created when Visual Studio calls Connect.Exec() method to load the Add In.

The Add In loads a list of all solution files in Main Form Timer Tick event. Timer Tick event happens a few milli seconds after the MainForm OnLoad event. Keeping loading of files in Timer Tick event helps in quick loading of MainForm and makes the UI more responsive.

private void timer2_Tick(object sender, EventArgs e)
{
    timer2.Enabled = false;
    CreateSolutionFileList();
    fileText = File.ReadAllText(FilePathRsFilesTxt);
}		

The Add In shortcut Alt + G is created in Connect.OnConnection() event. OnConnection() is called by Visual Studio when the Add In loads.

     public void OnConnection(object application, 
	ext_ConnectMode connectMode, object addInInst, ref Array custom)
        {
		.
		.
		.
                    AddShortcut(command, "Global::Alt+G", "Edit");
                }
                catch (System.ArgumentException)
                {
                }
            }
        }

        private void AddShortcut(Command cmd, String szKey, String szMenuToAddTo)
        {
            if ("" != szKey)
            {
                // a default keybinding specified
                object[] bindings;
                bindings = (object[])cmd.Bindings;
                if (0 >= bindings.Length)
                {
                    // there is no preexisting key binding, so add the default
                    bindings = new object[1];
                    bindings[0] = (object)szKey;
                    cmd.Bindings = (object)bindings;
                }
            }

            if ("" != szMenuToAddTo)
            {
                CommandBars commandBars = (CommandBars)_applicationObject.CommandBars;
                Microsoft.VisualStudio.CommandBars.CommandBar commandBar =
 	(Microsoft.VisualStudio.CommandBars.CommandBar)commandBars[szMenuToAddTo];
                cmd.AddControl(commandBar, commandBar.Controls.Count);
            }
        }

Points of Interest

To create a file list quickly, without showing cmd.exe window, I set System.Diagnostics.Process.StartInfo.WindowStyle property to false. Following is the code for CreateSolutionFileList():

private void CreateSolutionFileList()
{
    try
    {
        string folders = "";

        foreach (Project p in ApplicationObject.Solution.Projects)
        {
            folders += " " + DQuote(Connect.GetFolder(p.FullName));
        }

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        proc.EnableRaisingEvents = false;
        proc.StartInfo.FileName = "cmd";
        proc.StartInfo.Arguments = @"/c dir /s/b/a-d " + folders + ">" + 
			DQuote(FilePathRsFilesTxt);
        proc.Start();

        bool delay = !File.Exists(FilePathRsFilesTxt);

        if (delay)
        {
            System.Threading.Thread.Sleep(800); // let DOS create the file
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error occurred: " + ex.Message + "\n\n" + 
        ex.StackTrace, "GoToFile 2.0", MessageBoxButtons.OK, 
        MessageBoxIcon.Error);
    }
}

To filter out the matched files, I first used RegEx to filter out matched files from file generated by dir /s/b/a-d command. Then I created DataTable to show in GridView and applied DataView filter to make sure that only the required files appear in the list. Following is the code for RefreshFileList():

private bool RefreshFileList(string filter)
{
    filter = filter.ToLower();

    bool hasMoreFiles = false;

    try
    {
        if (filter == "")
        {
            HideList();

            return hasMoreFiles;
        }

        Regex match = new Regex("^.*(" + 
        (filter.Contains("*") ? filter.Replace("*", "") 
        : filter) + ").*$", RegexOptions.Multiline | RegexOptions.IgnoreCase);

        MatchCollection c = match.Matches(fileText);

        if (c.Count > 0)
        {
            #region ShowList
            DataTable table = new DataTable();

            table.Columns.Add("FileName");
            table.Columns.Add("FilePath");

            int i = 0;

            foreach (Match var in c)
            {
                if (i++ == 99 && !showAll)
                {
                    hasMoreFiles = true;

                    break;
                }

                DataRow row = table.NewRow();

                row["FileName"] = GetFileName(var.Value);
                row["FilePath"] = var.Value.Trim();

                table.Rows.Add(row);
            }

            DataView view = table.DefaultView;

            view.RowFilter = "FileName LIKE '%" + 
            (filter.Contains("*") ? filter.Replace("*", "") : filter) + "%'";
            view.Sort = "FileName";

            if (view.Count > 0)
            {
                int hx = view.Count <= 11 ? view.Count * 
                (dataGridView1.RowTemplate.Height + 1) : 200;
                Height = h + hx;

                dataGridView1.DataSource = view;
                dataGridView1.Visible = true;

                if (hasMoreFiles)
                {
                    label1.Text = "Showing top 99 matches 
                    (Press Ctrl+F to toggle show all)";
                }
                else
                {
                    label1.Text = view.Count + (view.Count == 1 ? 
                    " file " : " files ") + "found";
                }

                return hasMoreFiles;
            }
     
            #endregion
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error occurred: " + ex.Message + 
        "\n\n" + ex.StackTrace, "GoToFile 2.0", 
        MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

    HideList();

    return hasMoreFiles;
} 

History

  • 20th March, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Syed Rafey Husain
Software Developer (Senior)
Pakistan Pakistan
Software Developer from Karachi, Pakistan.

Comments and Discussions

 
GeneralNice work but ... PinmemberJay Zhu20-Mar-09 4:43 
GeneralFour Missing Things In Ctrl + D PinmemberSyed Rafey Husain20-Mar-09 5:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140821.2 | Last Updated 20 Mar 2009
Article Copyright 2009 by Syed Rafey Husain
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid