Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Methods Navigation with a Drop-Down List

0.00/5 (No votes)
7 Aug 2009 1  
An easy to use, low real estate Methods DDL navigation tool.

Example of Methods DDL

Introduction

This is an alternate to the Source Code Outliner Power Toy and the Class View. It is an add-in that places a drop-down list (DDL) of methods next to the Help menu. Select a method and jump to that spot in code, the full line is highlighted and the first line is scrolled to the top of the code window.

This project exercises VS. NET 2008 IDE Extensibility. The first incarnation was a VB6 project to do the same DDL for the MS Office IDE. I missed the Methods DDL functionality in VS.NEt. I'm posting the project so others can either use (at their own risk) or customize for their own use.

Background

The Methods DDL overcomes shortcomings of the std. IDE navigation.

  • The std. dual DDL approach is cumbersome for navigation, requiring selection from two DDLs.
  • After selecting the navigation target, because the line is not highlighted, it can be difficult to find the selected line.
  • The std. methods DDL has used and unused methods, so it can be quite long.

The Methods DDL takes less real estate than the Source Code Outliner Power Toy, and is simpler to navigate than the class viewer.

Using the Code

Two downloads are available: an installer and source code.

To install and use the add-in:

  • Unzip and run Setup.exe. (Uninstall from Add/Remove Programs).
  • When VS is opened, you'll see the DDL next to the Help DDM. (The first time VS is opened after the install, you may see two instances of the DDL. The second DDL will disappear the next time VS is started.)
  • When a module (std or class) is opened for editing, the DDL list repopulates.
  • The list is updated as you add or delete methods in your source code.
  • Drop down the list of methods and select one to navigate to the first line of the target method.
  • The code pane scrolls if possible so that the first line of the target method is at the top of the pane.

The following is for developers interested in modifying/working with the code:

The source code project is for VS2008 in VB.NET. Unzip to your Visual Studio 2008 Projects folder. The source code is set up to run in debug and uses a special .addin. The special .addin is named "Proc_DDL - For Testing.AddIn" and needs to be placed in "C:\Documents and Settings\%USERNAME%\My Documents\Visual Studio 2008\Addins". You will need to unzip the special .addin from the Debug_Addin zip to the Addins folder. Only the Assembly node in the .addin is different between the debug and release usage; examples are shown below. Be sure the installed version is uninstalled via Add/Remove Programs; if you plan to use the project in Debug mode, then open the .sln with VS2008.

<Assembly>C:\Documents and Settings\%USERNAME%\My Documents\Visual 
       Studio 2008\Projects\Proc_DDL\Proc_DDL\bin\Proc_DDL.dll</Assembly>

The installable uses a different .addin with an Assembly line like this:

<Assembly>Proc_DDL_Addin\Proc_DDL.dll</Assembly>

Which locates the add-in DLL in the Proc_DDL_Addin folder of the target add-in folder, in my case:

[PersonalFolder]\Visual Studio 2008\Addins

Where [PersonalFolder] is C:\Documents and Settings\%USERNAME%\My Documents (the default location in the setup project).

If you need to switch the project back from Debug to Release mode, special care is needed with the .addin files. For Debug mode, use "Proc_DDL - For Testing.AddIn". For Release mode, rename "Proc_DDL - For Testing.AddIn" to "Proc_DDL - For Testing.AddIn_" so the release version "Proc_DDL.AddIn" will work. Reverse that process to go back to Debug mode. The .addin specifies where the .dll is located. "Proc_DDL - For Testing.AddIn" specifies the project folder with the debug info. "Proc_DDL.Addin" specifies the target installation folder from the setup project, in this case "[PersonalFolder]\Visual Studio 2008\Addins\Proc_DDL". Both .addins are actually placed in "[PersonalFolder]\Visual Studio 2008\Addins":

  1. for testing/debug "Proc_DDL - For Testing.AddIn" must be the active .addin,
  2. an install will put "Proc_DDL.Addin" in "[PersonalFolder]\Visual Studio 2008\Addins".

If both .addins are active, the Methods DDL will not work. Hence the renaming of the test version of .addin when you install the add-in for "release" usage.

Carlos Quintero, MzTools, has a detailed discussion of the .addin locations, see Default .AddIn file locations for Visual Studio add-ins. For MzTools, internationalization requires a different kind of DLL locator, so the Registry has SatelliteDLLName and Path info for MzTools (registered with RegAsm).

If you plan on modifying the source code, please visit the MSDN library, under Visual Studio 2008, find "Visual Studio Automation and Extensibility", subtopic "Walkthrough: Debugging an Add-in Project."

Running the project in debug requires setting the configuration to "Debug", and under Tools/Options, expand the Debugging node, then under General, clear "Warn if no user code on launch". This prevents an annoying warning popping up during testing. Regardless of the warning, test runs work fine (as long as the .addin is configured correctly).

Points of Interest

In the VB6 incarnation for the MS Office IDE, I was unable to get at IDE events, so I used a Refresh button to restock the DDL of methods. The VS IDE events expose two important improvements for the Methods DDL: windows and code model events (without these events, a Refresh button would be needed as in the MS Office IDE).

Avenues of exploration are:

  • IDE events which are quite rich in VS Extensibility,
  • Menu bars and controls, and
  • The code model navigation, pane, and text management.

To get at the target events, begin with IDTExtensibility2.OnConnection which gets wired up when the Extensibility type project gets selected under the [New>Project>Other Project Types] menu in Visual Studio. A casting cascade is needed to go from the general connection object variable (oApp) down to Events2 which is needed for oWinEvents and oCodeModelEvents. (I relied on MSDN to get samples of much of this code.)

Public Sub OnConnection( _
ByVal oApp As Object, _
ByVal oConnectMode As ext_ConnectMode, _
ByVal oThis_AddIn As Object, _
ByRef custom As Array) _
    Implements IDTExtensibility2.OnConnection

    Dim oEvents2 As EnvDTE80.Events2

    oDTE2 = CType(oApp, DTE2)
    oAddIn = CType(oThis_AddIn, AddIn)

    oEvents2 = CType(oDTE2.Events, EnvDTE80.Events2)
    oWinEvents = CType(oEvents2.WindowEvents(Nothing), EnvDTE.WindowEvents)
    oCodeModelEvents = oEvents2.CodeModelEvents(Nothing)

The event objects that must work in the VS IDE need to be public with events as implemented in the following code segment:

Public Class Connect
 Implements IDTExtensibility2
    Private oDTE2 As DTE2
    Private oAddIn As AddIn
    Public WithEvents oWinEvents As EnvDTE.WindowEvents
    Public WithEvents oCodeModelEvents As EnvDTE80.CodeModelEvents
    Public WithEvents cbComboBox As CommandBarComboBox
    'Public WithEvents cbButton As CommandBarButton '--- For exploration only
    Private oTbl As DataTable
    Private oDocCurrent As Document

pb_ProcDDLStarted is a flag used to ensure that there is only one DDL insert; it is set to False during class initialization.

If you want to relocate or resize the Methods DDL, reposition by changing cbControl_Help as you like or the width and drop down lines for cbComboBox.

If Not pb_ProcDDLStarted Then
   pb_ProcDDLStarted = True
      Dim oCommands As Commands2 = CType(oDTE2.Commands, Commands2)

      '--- Find the MenuBar command bar, which is the top-level
      '    command bar holding all the main menu items:
      Dim cbs As CommandBars = CType(oDTE2.CommandBars, CommandBars)
      Dim mbCommandBar As CommandBar = cbs.Item("MenuBar")

      '--- Find the Help command bar control on the MenuBar command bar:
      Dim cbControl_Help As CommandBarControl = mbCommandBar.Controls.Item("Help")
      Dim iCmdPosition As Integer = CInt(CType(cbControl_Help.Index, Long) + 1)

      Dim cbControls As CommandBarControls = mbCommandBar.Controls
      '??? Abit odd to be using a Microsoft.Office.Core enumeration
      'cbButton = CType(cbControls.Add(MsoControlType.msoControlButton), CommandBarButton)
      '??? Why use Exec & QueryStatus when there's a Click Event
      '    which conforms to previous convention,
      '??? ??? Not to mention it works as before
      '       (Exec & QueryStatus vaguely documented IMHO)
      cbComboBox = CType(cbControls.Add(MsoControlType.msoControlComboBox), _
                         CommandBarComboBox)

      Try
          With cbComboBox
               .Enabled = False
               .Width = 300
               .DropDownLines = 70
          End With

oWinEvents_WindowActivated calls a refresh sub to repopulate the methods DDL if window.kind is "Document." OnCodeElement_Added and OnCodeElement_Deleted handle refreshing after adding and deleting methods. OnCodeElement_Changed was not necessary, see line 284 (if the code changes, the start point is handled automatically) (I left OnCodeElement_Changed in comments in case you want to use it).

(I also left in the code for a Refresh button in the event that you want to play with that.)

Refresh Method

Start by examining sb_Refresh. sb_OutlineCode and sb_OutlineElement populate oTbl which is used by sb_PopulateCombobox. The outline functionality walks through the file code model, then the code elements recursively to capture all the function names.

Go To DDL Selection

Wiring up cbComboBox to handle the selection of a method is done in OnConnection, see the pb_ProcDDLStarted block above. The code is pretty straightforward except for the use of MsoControlType.msoControlComboBox. The use of the MS Office control types in Visual Studio seemed a bit odd to me.

sb_OutlineCode is used again except the search function moves to the start point of the selected method, selects the entire line, then attempts to move the start point for the function to the top of the pane. There is a side effect if the code is collapsed; when the + sign is clicked on a fully selected line, the expanded section is all selected. The following code does the move to start point, line select, and code pane adjustment.

If oCTElems.Item(i).Name = sProcName Then
    Dim oSel As TextSelection _
        = CType(oDocCurrent.Selection, TextSelection)

    Dim oTextPane As TextPane _
        = oSel.TextPane

    With oSel
        .MoveToPoint(oCTElems.Item(i).StartPoint)
        .SelectLine()
        oTextPane.TryToShow(oCTElems.Item(i).StartPoint, vsPaneShowHow.vsPaneShowTop)
    End With

End If

History

  • First release: 2009.07.23.
  • Beta test: 2009.07.27: David Larson reported two DDLs for initial use of the add-in. Subsequent uses of the add-in only had one DDL. Despite special care to prevent more than one DDL, the VS IDE was firing the add-in onConnection twice on the first use. During testing, I saw the same initial two DDLs.
  • Beta test: 2009.07.27. The add-in does not work with VS2008 Express Edition.
  • 2009.08.07: Added handler for Forms Designer. Add-in was not skipping the outline for design documents.
  • 2009.08.07: Tested in WPF to be sure the outliner was skipped for XAML documents.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here