How to migrate from COM components to add-ins


In this topic


About migrating from COM components to add-ins

Add-ins are a new way to add custom functionality to the ArcGIS Desktop applications. Add-ins provide several benefits over Component Object Model (COM) components including simplified development and deployment. For example, add-ins do not use COM component categories and do not require registration. Instead, add-ins are automatically discovered and incorporated into their target application at startup.
ArcGIS Desktop applications support a fixed set of add-in types, including the most popular types used in the classic COM based extensibility model. The following add-in types are supported in the current release:
  • Buttons and tools
  • ComboBox controls
  • Menus (including root menus and context menus)
  • MultiItems
  • Toolbars (including premier toolbars)
  • Tool palettes
  • Dockable windows
  • Application extensions
  • Editor extensions
The preceding add-in types are the only customization points available in the current add-in model. Custom components, such as renderers, feature layers, edit tasks, and property pages are not supported.
For more information on add-ins, see Building add-ins for ArcGIS Desktop.
Although add-ins provide several benefits over the classic COM component model, there is no requirement to convert COM components to add-ins (the COM component model is still the backbone of ArcGIS). If you decide add-ins are a better solution for your customizations going forward, you can manually convert to these; unfortunately, there is no utility to automatically perform this task.

Creating a project

Do the following steps to create an add-in project:
  1. Install the ArcObjects .NET software development kit (SDK). 
  2. Create a desktop add-in project using the ESRI Desktop Add-In New Project template.
  3. Complete the Welcome page (for example, the add-in name, description, and so on).
  4. Select the types you want in your add-in (for example, a button).
  5. Click Finish. The add-in project is created with the Button1.cs, Config.esriaddinx, and Config.Designer.cs files.
For more information about creating an add-in project using the Add-In Wizard, see Building custom UI elements using add-ins.

Using the Config.esriaddinx file

Add-ins take advantage of declarative programming that reduces and simplifies the coding burden and helps separate the presentational aspects from the implementation details. Declarations are located in the Config.esriaddinx file, which is an Extensible Markup Language (XML) file.
The first section of the file relates to metadata for the add-in including its name, ID, description, image, and version. This metadata identifies and describes the add-in as a whole (this information appears in the Add-In Manager). The following code example shows the metadata tags:
[XML]
<Name>ArcMapAddin1</Name>
<AddInID>{07dc0f83-731e-4b98-9e0a-e219bff28bf8}</AddInID>
<Description>Type a description for the add-in.</Description>
<Version>1.0</Version>
<Image>Images\AddInSample.png</Image>
<Author>John Locke</Author>
<Company>Dharama</Company>
<Date>7/28/2009 2:42:45 PM</Date>
Later in the Config.esriaddinx file, there is an AddIn element that contains all the customizations defined in the add-in. The AddIn element has a language attribute that designates the add-ins' development environment (common language runtime [CLR] or Java). It also has a library attribute that indicates to the add-in framework the related assembly to load and finally, it has a namespace attribute, which is the default namespace for all classes in the assembly (classes are covered later in this topic). See the following code example:
[XML]
<AddIn language="CLR" library="Acme.dll" namespace="AcmeTools">...</AddIn>
When you created the add-in project, you selected a target application, such as ArcMap or ArcGlobe. This selection generated a corresponding element under the AddIn element. This element enables the add-in framework to automatically determine which application the add-in is targeting, for example, an ArcMap button will not be available in ArcGlobe. 
Under ArcMap, for example, is a Controls element that holds declarations for all buttons, tools, combo boxes, multi-items, and tool palettes. Parallel to this are sections for toolbars, menus, dockable windows, and extensions (each of these sections are also discussed later in this topic).
[XML]
<AddIn language="CLR" library="Acme.dll" namespace="AcmeTools">
  <ArcMap>
    <Commands>
      <Button
        id="ESRI_SelectionSample_ToggleDockWinBtn"
        class="ToggleDockWinBtn"
        caption="OpenDockWin"
        category="Framework AddIn Samples"
        image="Images\ToggleDockWinBtn.png"
        tip="Toggle dockable window."
        message="Open dockable window.">
        <Help heading="Add-in button">Click the button to show the selection count dockable window.</Help>
      </Button>
    </Commands>
  </ArcMap>
</AddIn>

Converting commands to controls

Buttons, tools, tool palettes, multi-items, and combo boxes are declared under the Controls element. Control declarations are visible on the Customize dialog box. For example, an ArcMap button declaration appears as a regular command item on ArcMap's Customize dialog box. From here, the button can be dragged onto any toolbar or menu like a regular COM command. 
All control add-in types have a declarative portion and an active portion. The active or imperative portion is equivalent to the classic instruction based programming model. The Add-In Wizard automatically writes the declarations for these types and stubs out generic classes where you can add your custom business logic.

Setting the caption, category, ToolTip, help, and image

In COM component projects, the static data associated with framework types, such as caption and ToolTip, is stored alongside the component's business logic. With add-ins, this data is separated from implementation and is instead part of the declaration inside the Config.esriaddinx file.
The following code example shows a button example. Notice how the class attribute is used to associate the active code portion with the declarative portion. 
[XML]
<Commands>
  <Button
    id="ESRI_ArcMapAddin1_ZoomToLayerCSharp"
    class="ZoomToLayerCSharp"
    caption="Zoom To Layer CSharp"
    category="Add-in Developer Samples"
    image="Images\ZoomToLayerCSharp.png"
    tip="Zoom To Layer CSharp ."
    message="Zoom to the extent of the active layer in the TOC.">
    <Help heading=" Zoom To Layer button">
      This is the add-in button. Click the button to zoom to the extent of the active layer in the TOC.
    </Help>
  </Button>
</Commands>
Add-ins never expose a Name (the programmatic ID of a COM component) and instead, have an ID that can be used anywhere a unique identifier (UID) is expected. See the following code example:
[C#]
UID extID = new UIDClass();
extID.Value = @"ESRI_SelectionSample_SimpleExtension";
IExtension selectionExt = ArcMap.Application.FindExtensionByCLSID(extID);
[VB.NET]
Dim extID As UID = New UIDClass()
extID.Value = "ESRI_SelectionSample_SimpleExtension"
Dim selectionExt As ESRI.ArcGIS.esriSystem.IExtension = ArcMap.Application.FindExtensionByCLSID(extID)

OnCreate and the Hook parameter

Add-ins do not have an OnCreate function; instead, all initialization logic should be moved to the add-ins constructor. In addition, instead of obtaining a reference to the running application via a passed Hook parameter, add-in projects have an application class that is automatically generated inside the Config.Designer.cs file. For example, ArcMap projects have an ArcMap class and ArcGlobe projects have an ArcGlobe class.
These application classes expose several static members for accessing commonly used types. For example, inside an ArcMap add-in, instead of casting a Hook parameter to IApplication and calling the Document property to get a reference to IMxDocument, call ArcMap.Document.
The following table shows a list of the available types and static members in an ArcMap add-in:
Type
Static members
IApplication
ArcMap.Application
IMxDocument
ArcMap.Document
IMxApplication
ArcMap.ThisApplication
IDockablewindowManager
ArcMap.DockableWindowManager
IDocumentEvents
ArcMap.Events

Enabled and Checked properties

Add-in buttons and tools do not expose separate Enabled and Checked properties like their COM equivalents. Instead, add-in developers can override the OnUpdate method that is also called periodically and from here, you can update the button and tool's Enabled and Checked properties (this.Enabled and this.Checked). The data members for caching the enabled and checked states are already created in the base class. See the following code example:
[C#]
protected override void OnUpdate()
{
    this.Enabled = (m_editor.EditState == esriEditState.esriStateEditing);
}
[VB.NET]
Protected Overrides Sub OnUpdate()
Me.Enabled = (m_editor.EditState = esriEditState.esriStateEditing)
End Sub

Converting toolbars and menus

Add-in toolbars and menus are purely declarative. Unlike buttons and tools, toolbars and menus do not have an active portion and require no coding. To add a toolbar or menu to your add-in project, manually edit the Config.esriaddinx file. Toolbar and Menu elements are the placeholders for all toolbars and menus in an add-in, and are defined under the target application element (see the following code examples).
Each Toolbar element defines a unique toolbar. The Items sub-element within the Toolbar element lists all the toolbar constituents. Menus work exactly the same. Toolbars can host Button, Tool, Tool Palette, ComboBox, and Menu items. Menus can host Button, MultiItem and other Menu items. Each item must specify a refID attribute to associate the actual control with the toolbar or menu. 
Existing classic COM objects can be referenced using their ProgID.

Defining premier toolbars

The showInitially attribute is provided on Toolbar elements to indicate a Premier Toolbar. Premier toolbars automatically appear the first time their target application starts. See the following code example:
[XML]
<ArcMap>
  <Toolbars>
    <Toolbar caption="Add-in Toolbar" id="ZoomToLayerToolbar" showInitially="true">
      <Items>
        <Button refID="ESRI_ArcMapAddin1_ZoomToLayerCSharp"/>
        <Tool refID="esriArcMapUI.SelectByLayerCommand"/>
      </Items>
    </Toolbar>
  </Toolbars>
</ArcMap>

Defining root menus and context menus

To define a root menu, use the isRootMenu attribute. Root menus appear in the [Menus] category on the Customize dialog box. Similarly, use the isShortcutMenu attribute to declare a context menu. See the following code example:
[XML]
<ArcMap>
  <Menus>
    <Menu id="AcmeRootMenu" caption="ACME Rootmenu" isRootMenu="true">
      <Items>
        <Button refID="ESRI_SelectionSample_ToggleDockWinBtn"/>
      </Items>
    </Menu>
  </Menus>
</ArcMap>

Converting dockable windows

The add-in project and item templates stub out the basic code for dockable windows when one is selected. Similar to buttons and tools, the caption is declared in the configuration file and there are no OnCreate and OnDestroy overrides. Use the dockable window's constructor and destructor for code initialization and cleanup. Dockviews now support an initial placement and image.  See the following code example:
[XML]
<DockableWindows>
  <DockableWindow
    id="ESRI_SelectionSample_SelCountDockWin"
    class="SelCountDockWin+AddinImpl"
    caption="Selected Features Count"
    image="Images\ToggleDockWinBtn.png">
    <InitialPlacement height="300" width="300" state="pinned" position="right"/>
  </DockableWindow>
</DockableWindows>

Converting extensions

Extensions load in one of the following ways:
  • Automatically at start-up with the application
  • Just-in-time (by request only)
Add-in extensions support both of these extension loading schemes. Instead of registering your extension in a special component category, set the autoLoad attribute as follows:
  • Use autoLoad="true" to start the extension with the application.
  • Use autoLoad="false" to delay load the extension.
If you want your extension to appear on the ArcGIS Extension dialog box, use showInExtensionDialog="true." In this case, make sure the productName and Description attributes are specified, as this information shows on the ArcGIS Extension dialog box. See the following code example:
[XML]
<Extensions>
  <Extension
    id="ESRI_SelectionSample_SimpleExtension"
    autoLoad="true"
    productName="Selection Sample Extension"
    showInExtensionDialog="true"
    class="SelectionExtension">
    <Description>
      This is a selection sample extension.
    </Description>
  </Extension>
</Extensions>
In your class implementation, override OnSetState and OnGetState to set and get your extension's state. See the following code example:
[C#]
protected override bool OnSetState(ExtensionState state)
{
    //Users can optionally check license here.
    s_state = state;
    return base.OnSetState(state);
}

protected override ExtensionState OnGetState()
{
    return base.OnGetState();
}
[VB.NET]
Protected Overrides Function OnSetState(ByVal state As ExtensionState) As Boolean
' Users can optionally check license here.
s_state = state
Return MyBase.OnSetState(state)
End Function

Protected Overrides Function OnGetState() As ESRI.ArcGIS.Desktop.AddIns.ExtensionState
Return MyBase.OnGetState()
End Function
To persist data in your extension, override OnLoad and OnSave.

Wiring up document events

Add-ins simplify event handlers for document events by predefining the static member events on each of the application classes, for example, ArcMap.Events. See the following code example:
[C#]
ArcMap.Events.NewDocument += new
    ESRI.ArcGIS.ArcMapUI.IDocumentEvents_NewDocumentEventHandler(ArcMap_NewDocument);

void ArcMap_NewDocument()
{
    IActiveViewEvents_Event pageLayoutEvent = ArcMap.Document.PageLayout as
        IActiveViewEvents_Event;
    pageLayoutEvent.FocusMapChanged += m_focusMapChangedEH;
    WireSelectionChangedEvent();
}
[VB.NET]
AddHandler ArcMap.Events.NewDocument, AddressOf ArcMap_NewOpenDocument

Private Sub ArcMap_NewOpenDocument()
    Dim pageLayoutEvent As IActiveViewEvents_Event = TryCast(ArcMap.Document.PageLayout, IActiveViewEvents_Event)
    AddHandler pageLayoutEvent.FocusMapChanged, m_focusMapChangedEH
    WireSelectionChangedEvent()
End Sub

Registering add-ins

Add-ins do not need to be registered into COM component categories. Do not add your COM component category registration code into your new add-in, including the globally unique identifier (GUID) and ProgID class attributes.


See Also:

Building add-ins for ArcGIS Desktop
Walkthrough: Building custom UI elements using add-ins