2

I am working on an ArcObjects addin for Desktop 10.1. I am using the SelectionExtension as a template for my addin. I was unable to listen for events through a dockable window, so at others' suggestions I am trying to use an extension. I tried an editor extension, but for some reason the OnStartup() method never fired. Now just to narrow down what is going on, I have a regular extension that I can enable/disable in the Extension Manager window. However, it appears that there is something else going on. The extension is visible, but I am unable to enable it in the Extension Manager window. I know these are two seemingly unrelated issues, but it seems that the OnStartup() method of the new regular extension is not firing as well. I am at a loss as to what I have done wrong. Is there any reason that the OnStartup methods aren't firing, and would that relate to the enable/disable state in the Extension Manager window?

EDIT: When working the extension should load a toolbar, consisting of a button and a combo box. The combo box will list all editable layers of an edit session. The button will toggle on/off a dockable window that has several textboxes corresponding to fields in the selected combo box layer. The combo box will also have next and previous to move through the records, and an update button to save any edits made to the attributes. Also on the dockable window, there are two picture boxes that will load images linked to each feature.

Ideally, I would like the toolbar, its items, and the dockable window enabled/disabled with edit session start/stop. The button will simply toggle on/off the dockable window.

Below is my wall of code for the Extension. Not one of the MessageBoxes pop up.

Imports ESRI.ArcGIS.Editor
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports System.Windows.Forms
Imports ESRI.ArcGIS.Desktop.AddIns

Namespace MyAddinTools
    Public Class MyAddinExtension
        Inherits ESRI.ArcGIS.Desktop.AddIns.Extension

        Private Shared s_dockWindow As ESRI.ArcGIS.Framework.IDockableWindow
        Private Shared s_extension As MyAddinExtension
        Private m_map As IMap
        Private m_editlayers As IEditLayers
        Private m_hasSelectableLayer As Boolean
        Private m_EditEvents As IEditEvents_Event

        'Constructor routine
        Public Sub New()
            MessageBox.Show("Extension constructed...")
        End Sub

        'Methods called by ArcObjects
        Protected Overrides Sub OnStartup()
            MessageBox.Show("Extension loaded...")
            s_extension = Me  
            Initialize()
        End Sub
        Protected Overrides Sub OnShutdown()
            Uninitialize()
            m_map = Nothing
            s_dockWindow = Nothing
            s_extension = Nothing
            MyBase.OnShutdown()
        End Sub

        'Methods for Extension Manager Window
        Protected Overrides Function OnSetState(ByVal state As ExtensionState) As Boolean
            Me.State = state
            If state = ExtensionState.Enabled Then
                Initialize()
            Else
                Uninitialize()
            End If
            Return MyBase.OnSetState(state)
        End Function
        Protected Overrides Function OnGetState() As ExtensionState
            Return MyBase.OnGetState()
        End Function

        'Helper Methods
        Private Sub Initialize()
            If s_extension Is Nothing Or Me.State <> ExtensionState.Enabled Then
                Return
            End If

            'Event wiring
            Dim avEvent As IActiveViewEvents_Event = TryCast(My.ArcMap.Document.FocusMap, IActiveViewEvents_Event)
            AddHandler avEvent.ItemAdded, AddressOf LayerAddedOrDeleted_Handler
            AddHandler avEvent.ItemDeleted, AddressOf LayerAddedOrDeleted_Handler
            m_EditEvents = TryCast(My.ArcMap.Editor, IEditEvents_Event)
            AddHandler m_EditEvents.OnStartEditing, AddressOf OnStartEditing_Handler
            AddHandler m_EditEvents.OnStopEditing, AddressOf OnStopEditing_Handler

            MyAddinDockWin.SetEnabled(True)
        End Sub
        Private Sub Uninitialize()
            If s_extension Is Nothing Then
                Return
            End If

            'Detach event handlers
            Dim avEvent As IActiveViewEvents_Event = TryCast(m_map, IActiveViewEvents_Event)
            RemoveHandler avEvent.ItemAdded, AddressOf LayerAddedOrDeleted_Handler
            RemoveHandler avEvent.ItemDeleted, AddressOf LayerAddedOrDeleted_Handler
            avEvent = Nothing
            RemoveHandler m_EditEvents.OnStartEditing, AddressOf OnStartEditing_Handler
            RemoveHandler m_EditEvents.OnStopEditing, AddressOf OnStopEditing_Handler

            MyAddinDockWin.SetEnabled(False)
            LayerComboBox.ClearAll()

        End Sub
        Private Sub LayerAddedOrDeleted_Handler(ByVal Item As Object)
            '--Invoked when items are added to or deleted from map
            m_map = My.ArcMap.Document.FocusMap
            FillComboBox()
        End Sub
        Private Sub OnStartEditing_Handler()
            '--Invoked at the start of an edit session
            MessageBox.Show("Edit Session started...")
            'Wire up event handlers
            AddHandler m_EditEvents.OnSelectionChanged, AddressOf OnSelectionChanged_Handler

            'Update the UI
            m_map = My.ArcMap.Document.FocusMap
            FillComboBox()
            MyAddinDockWin.SetEnabled(True)
            LayerComboBox.SetEnabled(True)
            ToggleDockWinBtn.SetEnabled(True)
            OnSelectionChanged_Handler()
        End Sub
        Private Sub OnStopEditing_Handler()
            '--Invoked at the end of an edit session
            MessageBox.Show("Edit Session stopped...")
            'Unwire event handlers
            RemoveHandler m_EditEvents.OnSelectionChanged, AddressOf OnSelectionChanged_Handler

            'Update the UI
            LayerComboBox.ClearAll()
            MyAddinDockWin.SetEnabled(False)
            LayerComboBox.SetEnabled(False)
            ToggleDockWinBtn.SetEnabled(False)
        End Sub
        Private Sub OnSelectionChanged_Handler()
            ' If the dockwin hasn't been created yet
            If (Not MyAddinDockWin.Exists) Then
                Return
            End If

            ' Update the contents of MyAddinDockWin, when the selection changes in the map. 
            MessageBox.Show("Selection changed...")
            Dim featureLayer As IFeatureLayer
            Dim featSel As IFeatureSelection

            MyAddinDockWin.Clear()

            'Add code here to populate DockWin text boxes

        End Sub
        Private Sub FillComboBox()
            LayerComboBox.ClearAll()

            m_editlayers = TryCast(My.ArcMap.Editor, IEditLayers)

            Dim featureLayer As IFeatureLayer
            '--Loop through the layers in the map and add the layer's name to the combo box.
            Dim enumLayer As IEnumLayer = m_map.Layers(Nothing, True)
            enumLayer.Reset()
            Dim currentLayer As ILayer = enumLayer.Next()
            Do Until currentLayer Is Nothing
                If TypeOf currentLayer Is IDataset And Not TypeOf currentLayer Is IRasterLayer Then
                    Dim dataset As IDataset = currentLayer
                    '--Make sure layer is editable
                    If m_editlayers.IsEditable(currentLayer) Then
                        featureLayer = TryCast(currentLayer, IFeatureLayer)
                        If featureLayer Is Nothing Then
                            Exit Do
                        End If

                        'Add to combobox
                        LayerComboBox.AddItem(featureLayer.Name, featureLayer)
                    End If
                End If
                currentLayer = enumLayer.Next()
            Loop
        End Sub

        'Shared Methods
        Friend Shared Function IsExtensionEnabled() As Boolean
            If s_extension Is Nothing Then
                GetExtension()
            End If
            If s_extension Is Nothing Then
                Return False
            End If
            Return s_extension.State = ExtensionState.Enabled
        End Function
        Private Shared Function GetExtension() As MyAddinExtension
            'Call findExtension method to create the s_extension 
            'if the extension has been checked in the Extensions Window
            If s_extension Is Nothing Then
                Dim extID As UID = New UIDClass()
                extID.Value = My.ThisAddIn.IDs.MyAddinExtension
                ' Call FindExtension to load this just-in-time extension.
                My.ArcMap.Application.FindExtensionByCLSID(extID)
            End If
            Return s_extension
        End Function
        Friend Shared Function GetMyAddinDockWin() As ESRI.ArcGIS.Framework.IDockableWindow
            If s_extension Is Nothing Then
                GetExtension()
            End If

            ' Only get/create the dockable window if they ask for it
            If s_dockWindow Is Nothing Then
                Dim dockWinID As UID = New UIDClass()
                dockWinID.Value = My.ThisAddIn.IDs.MyAddinDockWin
                s_dockWindow = My.ArcMap.DockableWindowManager.GetDockableWindow(dockWinID)
                s_extension.OnSelectionChanged_Handler()
            End If

            Return s_dockWindow
        End Function

    End Class
End Namespace

Here is my Config.xml

<ESRI.Configuration xmlns="http://schemas.esri.com/Desktop/AddIns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Name>VACemeteryTools</Name>
  <AddInID>{a931f3f0-774a-47d0-a833-43bb799979eb}</AddInID>
  <Description>Tools for viewing and editing data.</Description>
  <Version>1.0</Version>
  <Image>Images\VACemeteryTools.png</Image>
  <Author>Me</Author>
  <Company>MyCompany</Company>
  <Date>9/8/2015</Date>
  <Targets>
    <Target name="Desktop" version="10.1" />
  </Targets>
  <AddIn language="CLR4.0" library="MyAddinTools.dll" namespace="MyAddinTools">
    <ArcMap>
      <DockableWindows>
        <DockableWindow id="MyAddinTools_MyAddinDockWin" class="MyAddinDockWin+AddinImpl" caption="My Addin Dock Window" image="Images\MyAddinDockWin.png">
          <InitialPlacement height="300" width="300" state="unpinned" position="float" />
        </DockableWindow>
      </DockableWindows>
      <Commands>
        <Button id="MyAddinTools_ToggleDockWinBtn" class="ToggleDockWinBtn" message="Toggle Dockable Window" caption="Toggle Dockable Window" tip="Toggle Dockable Window" category="My Addin Tools" image="Images\ToggleDockWinBtn.png" onDemand="false" />
        <ComboBox id="MyAddinTools_LayerComboBox" class="LayerComboBox" message="Select Layer" caption="Layer" tip="Layer" category="My Addin Tools" image="Images\LayerComboBox.png" sizeString="WWWWWWWWWW" itemSizeString="WWWWWWWWWW" showCaption="true" />
      </Commands>
      <Toolbars>
        <Toolbar id="MyAddinTools_MyAddinToolbar" caption="My Addin Tools" showInitially="false">
          <Items>
            <Button refID="MyAddinTools_ToggleDockWinBtn" />
            <ComboBox refID="MyAddinTools_LayerComboBox" />
          </Items>
        </Toolbar>
      </Toolbars>
      <Extensions>
        <Extension id="MyAddinTools_MyAddinExtension" class="MyAddinExtension" productName="My Addin Extension" showInExtensionDialog="true" autoLoad="false">
          <Description>Custom tools for editing and viewing records.</Description>
        </Extension>
      </Extensions>
    </ArcMap>
  </AddIn>
</ESRI.Configuration>

EDIT 2: According to the Extension Class documentation, whenever the Extension manager is opened or modified, OnGetState()/OnSetState() should fire, but my text boxes never appear. So it appears that these methods aren't firing.

UPDATE I've created a new addin consisting of only the extension. My code above works fine, with references to shared methods commented out, and messageboxes showing these being called. Once I add a button with only default code, the extension crashes ArcMap. In VS2010E, I delete the button and rebuild the addin, but it still crashes. I am at a loss on this one.

  • I would really need to see some code. What does this tool do (when it's working)... do you need something to start with ArcMap and wait for an event (like selection changed). I'm assuming you've tried debugging the tool with a breakpoint at the initializer to see if it's being loaded - right? – Michael Stimson Sep 8 '15 at 22:06
  • Does that start with a click of a button or do you need it to be listening to events as soon as ArcMap starts? Can you show your config.esriaddinx file too (XXXX out any personal or sensitive information to protect yourself) – Michael Stimson Sep 9 '15 at 3:18
  • @MichaelMiles-Stimson See above edits. – Barbarossa Sep 9 '15 at 3:37
  • change <Extension id=....autoLoad="false"> to <Extension id=....autoLoad="true"> and the initializer should be called when ArcMap starts, this however may be too soon as ArcMap isn't fully baked (not all components are alive) but you should be able to get your IEditor and wire the OnStartEditing event even at that early stage. – Michael Stimson Sep 9 '15 at 3:57
  • I have now tried both autoLoad settings, to no better outcome. After a restart of the whole system, now when I try to enable the extension in the extension manager window, ArcMap crashes. – Barbarossa Sep 9 '15 at 12:20
1

When you're starting ArcMap the OnStartup() is executed very early in the ArcMap startup process, at this stage ArcMap window is half-baked and trying to do too much is going to end badly. Not a lot of objects are initialized and ready at this stage and no windows have been created.

Instead wire the event My.ArcMap.Events.NewDocument which is fired at the end of the ArcMap startup process when the windows and objects are fully formed and just about to show the ArcMap application (and again for each new document...):

Protected Overrides Sub OnStartup()
    '
    ' TODO: Uncomment to start listening to document events
    '
    'WireDocumentEvents() // Esri start code...
    AddHandler My.ArcMap.Events.NewDocument, AddressOf ArcMapNewDocument
End Sub
Private Sub ArcMapNewDocument()
    ' TODO: Add code to handle new document event
    Debug.Print("NewDoc") ' wire further events here...
End Sub

It is safe however to unwire the event on the first run if you so wish:

Private Sub ArcMapNewDocument()
    ' TODO: Add code to handle new document event
    Debug.Print("NewDoc")   ' wire further events here
    RemoveHandler My.ArcMap.Events.NewDocument, AddressOf ArcMapNewDocument
End Sub

That way the extension is initialized only on the first run of ArcMap; I don't think there's much problem re-wiring the same event to the same delegate but just in case I think it would be safer to unwire it.

  • This works well on a newly created Addin consisting of only an extension (as does the OnStartup() method) with my above code. However, when I add an empty button, the extension no longer functions. – Barbarossa Sep 10 '15 at 13:00
1

After much trial and error, I found my solution after some research. The ESRI documentation for migrating COM components states that the Config.esriaddinx has a namespace attribute, which is the default namespace for all classes in the assembly. While using the ESRI sample code as a template, I had simply changed the namespace for each Class to match my addin. When I defined the namespace for each class, the assembly was looking for MyNamespace.MyNamespace.MyAddinComponent.

Once the class level namespace was removed (to where the assembly sees MyNamespace.MyAddinComponent) ArcMap no longer crashed and the debugger showed me other mistakes (don't trust ESRI sample code too much).

This is probably a beginner error, but perhaps someone could benefit from my facepalm moments throughout this process. Much thanks to Michael Miles-Stimson.

  • 1
    I'm glad it's working for you. I made a similar mistake a few years ago and I'm hardly a beginner so don't feel too bad about not picking it up straight away (I didn't, it took me hours to work it out). A healthy level of mistrust in code samples is a good thing I say; I tend to use them as a reference and re-type rather than copy and paste since that similar incident. – Michael Stimson Sep 10 '15 at 21:53
  • This caught me out too and I've been developing ArcObjects for 16 years!! – Vidar Oct 19 '17 at 11:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.