ProGuide Reusing Pro Commands - Esri/arcgis-pro-sdk GitHub Wiki

Language:      C#
Subject:       Framework
Contributor:   ArcGIS Pro SDK Team <[email protected]>
Organization:  Esri, http://www.esri.com
Date:          10/06/2024
ArcGIS Pro:    3.4
Visual Studio: 2022

This guide demonstrates how you can re-use existing ArcGIS Pro Commands in your Add-in. There are multiple variations of re-using ArcGIS Pro out-of-box Commands in your Add-in which are explained in this Pro Guide:

  • Reusing ArcGIS Pro Commands in your Add-in Ribbon UI by Reference
  • Reusing ArcGIS Pro Commands in your Add-in Ribbon UI in Code-Behind
  • Reusing ArcGIS Pro Commands in MVVM
  • Reusing ArcGIS Pro Commands in MVVM Code-Behind

The Reusing Po Commands community sample implements those variations outlined in this ProGuide.

In this topic

Understanding the Command Pattern in .NET

The Command Pattern in .NET is core to the methodology behind the SDK's implementation of 'Reusing of ArcGIS Pro Commands', hence a quick summary of the 'Command Pattern in .NET'. The Command Pattern in .NET is used to encapsulate a method invocation and is commonly used to handle control actions consistently across the platform and allowing a separation between the view (user interface) and the command handler method via data binding. An important component of the Command Pattern is the ICommand interface (System.Windows.Input namespace). In .NET a class that implements the ICommand interface can be used to handle any action event triggered by common WPF controls. These actions are linked either in XAML or in code-behind. Here is the ICommand interface declaration:

public interface ICommand
{
    event EventHandler CanExecuteChanged;
    bool CanExecute(object parameter);
    void Execute(object parameter);
}

Any implementation of ICommand interface requires two methods: CanExecute and Execute. CanExecute determines whether the command can be executed or not by returning true or false. If it returns false the caller (i.e. a button on the UI) disables the functionality on the UI. Execute runs the command's logic. CanExecuteChanged is invoked when changes occur that can change whether or not the command can be executed, hence ICommand is also suited to support the Model-View-ViewModel (MVVM) programming pattern used by the Pro Framework.

Using RelayCommand as an Implementation of ICommand

The ArcGIS Pro Framework provides the RelayCommand class to easily implement a Command’s “Execute” and “CanExecute” functionality. The framework's RelayCommand implementation is different from other common RelayCommand implementations in that by default it will add the command to the Pro application's main message pump meaning its CanExecute function will automatically be called several times a second. If you do not need this behavior, set supportsOnUpdate parameter to false in the appropriate constructor. If you do use this behavior, make sure you Disconnect the command from the pump when your dialog closes. RelayCommands automatically disable whenever the primary worker thread is busy. To override this behavior set disableWhenBusy parameter to false in the appropriate constructor. Note, RelayCommands in the message pump are automatically disabled once the Pro application begins to shut down. Here is a simple code snippet showing how to use RelayCommand.

ICommand sampleCmd = new RelayCommand(() =>
    { // Command Action logic goes here
      MessageBox.Show("Cmd Action");
    }, () =>
    { // Can execute logic goes here
      return true;
    });
// how to use the sample command
if (sampleCmd.CanExecute(null))
{
  // Yes the command can be run
  sampleCmd.Execute(null);
}

Reusing ArcGIS Pro Commands in your Add-in Ribbon UI by Reference

The ArcGIS Pro SDK allows you to use any ArcGIS Pro framework element in your Add-in tab including Buttons, Tools, Galleries. To implement existing ArcGIS Pro Elements in your Add-in you can simply add the appropriate element by reference in the Config.Daml of your Add-in. This will implement the UI Control just like it manifests itself in ArcGIS Pro, having the same behavior and the same user interface as in ArcGIS Pro. Each UI element in ArcGIS Pro has a unique identifier which is often referred to as the "DAML ID". In order to optain the desired DAML Id you can use the following methods:

  • The ArcGIS Pro SDK documentation includes a list of all out-of-box DAML Ids in the ArcGIS Pro DAML ID Reference
  • Use the ArcGIS "Pro Generate DAML Ids" utility ArcGIS Pro SDK for .NET utilities
  • Use the "Show command IDs on ScreenTips" option in the "Customize the ribbon options" dialog within ArcGIS Pro to view the Ids on the tooltip of each command.
  • Since Pro 2.6, you can search for DAML ids along with caption in the Customize the ribbon options page in ArcGIS Pro. With the proper DAML Id, for the example below is using "esri_mapping_bookmarksNavigateGallery" which brings up the Bookmarks Navigation dialog, simply add command buttons to your add-in by using the refID attribute in the button tag and reference the DAML Id.

In order to create a new tab on the Pro ribbon that contains the "Bookmarks Navigation" command follow these steps:

  1. Create a new ArcGIS Pro Add-in.
  2. Open config.DAML a replace the tabs and groups tags with the tags from the snippet below:
<modules>
  <insertModule ... >
    <tabs>
      <tab id="ReusingProCommands_Tab1" caption="Reuse Pro Cmds" keytip="T1">
        <group refID="ReusingProCommands_Group1"/>
      </tab>
    </tabs>
    <groups>
      <group id="ReusingProCommands_Group1" caption="Reuse Pro Commands" keytip="G1">
        <button refID="esri_mapping_bookmarksNavigateGallery" />
      </group>
    </groups>
    <controls>
      <!-- add your controls here -->
    </controls> 
  </insertModule>
</modules>
  1. Build and run the Add-in and the result should look like this: Reusing ArcGIS Pro Commands in your Add-in Ribbon UI by Reference DAML changes

Reusing ArcGIS Pro Commands in your Add-in Ribbon UI in Code-Behind

The ArcGIS Pro SDK allows you to use any ArcGIS Pro framework element's code-behind in your Add-in tab. This capability allows you to create your own button images and/or supplement the 'reused' ArcGIS Pro command's code-behind. You can use the ArcGIS Pro Framework’s “GetPlugInWrapper” method which be default returns and object that implements IPlugInWrapper, however, if that element is a command the returned objects will also implement the ICommand interface. Once you get a hold of the ICommand interface you are then able to utilize the Command’s “Execute” and “CanExecute” functionality. Note: if you want to re-use the image of an existing ArcGIS Pro command you can use the guideline shows in this FAQ: How do I use one of the ArcGIS Pro icons in my custom add-in?

In order to create a new tab on the Pro ribbon that contains the "Create Bookmark" command's code-behind with some custom functionality added on follow these steps:

  1. Create a new ArcGIS Pro Add-in.
  2. Add a new Button to your project and call the button CreateBookmark by using Add | New Item | ArcGIS | ArcGIS Pro | ArcGIS Pro Button item template.
  3. Open config.DAML a verify that you groups and controls tags have been updated to show the new button.
  4. Open CreateBookmark.cs and modify the OnClick method as follows:
...
using System.Windows.Input;
...

protected override void OnClick()
{
  // ArcGIS Pro Command's DAML ID. 
  var commandId = "esri_mapping_createBookmark";
  // get the ICommand interface from the ArcGIS Pro Button
  // using command's plug-in wrapper
  var iCommand = FrameworkApplication.GetPlugInWrapper(commandId) as ICommand;
  if (iCommand != null)
  {
    // Let ArcGIS Pro do the work for us
    if (iCommand.CanExecute(null))
    {
      iCommand.Execute(null);
      MessageBox.Show("Here is my own optional add-on functionality");
    }
  }
}
  1. If the button isn't added into your ReusingProCommands_Group1 in the Config.daml (e.g. you have another default group that it was copied in to) then edit the Config.daml to add the button reference into the ReusingProCommands_Group1 group.
 <group id="ReusingProCommands_Group1" caption="Reuse Pro Commands" keytip="G1">
   <button refID="esri_mapping_bookmarksNavigateGallery" />
   <button refID="ReusingProCommands_CreateBookmarks" size="large" />
 </group>
  1. Build and run the Add-in and the result should look like this and show the Create Bookmark dialog first: Reusing ArcGIS Pro Commands in your Add-in Ribbon UI by using existing code-behind
  2. After the "Borrowed code-behind" completes (after closing the Create Bookmark dialog) the add-on function will start running popping up the message box with the Here is my own optional add-on functionality string displayed.

Reusing ArcGIS Pro Commands in MVVM

Some ArcGIS Pro user interface elements like Pane, Dockpane, Custom Control, Embeddable Control, and Property Page require the MVVM pattern. The MVVM pattern (Model – View – ViewModel) facilitates the separation between the GUI development and the business logic or back-end logic coding. The Basic Pattern is:

  • The ViewModel is declared in DAML and implemented in code (C# or VB.Net): this would be the back-end business logic
  • The View is referenced in DAML and implemented as WPF UserControl (XAML): this is were this user interface is implemented.
  • The Model is optional In order to implement a Command in MVVM the GUI declaration (done in XAML) uses 'Data Binding' to reference an ICommand object which is then implemented in the View Model (business logic). Consequently the implementation in the View Model is simple the ICommand interface can be provided by using the ArcGIS Pro Framework’s “GetPlugInWrapper” method with any given ArcGIS Pro DAML Id.
  1. Create a new ArcGIS Pro Add-in.
  2. Add a new Dockpane to your project by using Add | New Item | ArcGIS | ArcGIS Pro | ArcGIS Pro Dockpane item template.
  3. Open the view "Dockpane1.xaml" and add a WPF button to your dockpane, change the content of your button to "Create Bookmark", and add the Command tag with Binding referencing CmdCreateBookmark as shown in the snippet below.
 <Grid>
    ...
    <DockPanel Grid.Row="0" ...>
      ...
    </DockPanel>
    <Button Content="Create Bookmark" Command="{Binding CmdCreateBookmark}" 
       HorizontalAlignment="Center" Grid.Row="1" VerticalAlignment="Center" 
       Width="120" Style="{DynamicResource Esri_Button}"/>
 </Grid>
</UserControl>
  1. Open the viewmodel "Dockpane1ViewModel.cs" and implement the ICommand interface "CmdCreateBookmark" referenced by the view as shown in the following snippet:
...
using System.Windows.Input;
...

public ICommand CmdCreateBookmark => 
       FrameworkApplication.GetPlugInWrapper("esri_mapping_createBookmark") as ICommand;
  1. Make sure the button reference to open the dockpane is added into the ReusingProCommands_Group1 group.
  2. Build and run the Add-in.
  3. Show your dockpane and click the "Create Bookmark" button. The result should look like this: Reusing ArcGIS Pro Commands in MVVM

Reusing ArcGIS Pro Commands in MVVM with code-behind customization

Taking the Command pattern in MVVM from the previous example to the next level we can change customize the code-behind of the existing ArcGIS Pro command. To do this we need to use the RelayCommand class which implements ICommand and allows you to specify your own "custom" implementation of Execute and CanExecute.

In order to customize the code-behind of the previous example follow these steps:

  1. Use the Add-in create in the previous example
  2. Open the viewmodel "Dockpane1ViewModel.cs" and replace the existing ICommand interface "CmdCreateBookmark" using the following snippet:
public ICommand CmdCreateBookmark =>
  new RelayCommand(() =>
    {
      // Execute implementation:
      // custom implementation first uses the out-of-box function
      var cmd = FrameworkApplication.GetPlugInWrapper("esri_mapping_createBookmark") as ICommand;
      cmd.Execute(null);
      // Now zoom back to full extent
      MapView.Active.ZoomToFullExtentAsync();
    }, 
    // CanExecute implementation: just use the out-of-box function direct        
    () => (FrameworkApplication.GetPlugInWrapper("esri_mapping_createBookmark") as ICommand).CanExecute(null)
    );
  1. Build and run the Add-in and the result should look like this and showing the Create Bookmark dialog as before, but the map should zoom back to the full extent after the Create Bookmark dialog closes.
⚠️ **GitHub.com Fallback** ⚠️