Skip to content

ProSnippets Framework

arcgisprosdk edited this page Jan 16, 2018 · 24 revisions
Language:              C#  
Subject:               Framework  
Contributor:           ArcGIS Pro SDK Team <[email protected]>  
Organization:          esri, http://www.esri.com  
Date:                  12/22/2017  
ArcGIS Pro:            2.1  
Visual Studio:         2015, 2017  
.NET Target Framework: 4.6.1  

Execute a command

IPlugInWrapper wrapper = FrameworkApplication.GetPlugInWrapper("esri_editing_ShowAttributes");
var command = wrapper as ICommand; // tool and command(Button) supports this

if ((command != null) && command.CanExecute(null))
  command.Execute(null);

Set the current tool

// use SetCurrentToolAsync
FrameworkApplication.SetCurrentToolAsync("esri_mapping_selectByRectangleTool");

// or use ICommand.Execute
ICommand cmd = FrameworkApplication.GetPlugInWrapper("esri_mapping_selectByRectangleTool") as ICommand;
if ((cmd != null) && cmd.CanExecute(null))
  cmd.Execute(null);

Activate a tab

FrameworkApplication.ActivateTab("esri_mapping_insertTab");

Activate/Deactivate a state - to modify a condition

// Define the condition in the DAML file based on the state 
if (activate)
  FrameworkApplication.State.Activate("someState");
else
  FrameworkApplication.State.Deactivate("someState");

Determine if the application is busy

// The application is considered busy if a task is currently running on the main worker thread or any 
// pane or dock pane reports that it is busy or intiializing.   

// Many Pro styles (such as Esri_SimpleButton) ensure that a button is disabled when FrameworkApplication.IsBusy is true
// You would use this property to bind to the IsEnabled property of a control (such as a listbox) on a dockpane or pane in order
// to disable it from user interaction while the application is busy. 
bool isbusy = FrameworkApplication.IsBusy;

Get the Application main window

System.Windows.Window window = FrameworkApplication.Current.MainWindow;

// center it
Rect rect = System.Windows.SystemParameters.WorkArea;
FrameworkApplication.Current.MainWindow.Left = rect.Left + (rect.Width - FrameworkApplication.Current.MainWindow.ActualWidth) / 2;
FrameworkApplication.Current.MainWindow.Top = rect.Top + (rect.Height - FrameworkApplication.Current.MainWindow.ActualHeight) / 2;

Close ArcGIS Pro

FrameworkApplication.Close();

Find a dockpane

// in order to find a dockpane you need to know it's DAML id
var pane = FrameworkApplication.DockPaneManager.Find("esri_core_ProjectDockPane");

Dockpane properties and methods

// in order to find a dockpane you need to know it's DAML id
var pane = FrameworkApplication.DockPaneManager.Find("esri_core_ProjectDockPane");

// determine visibility
bool visible = pane.IsVisible;

// activate it
pane.Activate();

// determine dockpane state
DockPaneState state = pane.DockState;

// pin it
pane.Pin();

// hide it
pane.Hide();

Dockpane undo / redo

// in order to find a dockpane you need to know it's DAML id
var pane = FrameworkApplication.DockPaneManager.Find("esri_core_contentsDockPane");

// get the undo stack
OperationManager manager = pane.OperationManager;
if (manager != null)
{
  // undo an operation
  if (manager.CanUndo)
    await manager.UndoAsync();

  // redo an operation
  if (manager.CanRedo)
    await manager.RedoAsync();

  // clear the undo and redo stack of operations of a particular category
  manager.ClearUndoCategory("Some category");
  manager.ClearRedoCategory("Some category");
}

Find a dockpane and obtain its ViewModel

// in order to find a dockpane you need to know it's DAML id.  

// Here is a DAML example with a dockpane defined. Once you have found the dockpane you can cast it
// to the dockpane viewModel which is defined by the className attribute. 
// 
//<dockPanes>
//  <dockPane id="MySample_Dockpane" caption="Dockpane 1" className="Dockpane1ViewModel" dock="bottom" height="5">
//    <content className="Dockpane1View" />
//  </dockPane>
//</dockPanes>

Dockpane1ViewModel vm = FrameworkApplication.DockPaneManager.Find("MySample_Dockpane") as Dockpane1ViewModel;

Open the Backstage tab

//Opens the Backstage to the "About ArcGIS Pro" tab.
FrameworkApplication.OpenBackstage("esri_core_aboutTab");

Access the current theme

//Gets the application's theme
var theme = FrameworkApplication.ApplicationTheme;
//ApplicationTheme enumeration
if (FrameworkApplication.ApplicationTheme == ApplicationTheme.Dark) {
    //Dark theme
}

if (FrameworkApplication.ApplicationTheme == ApplicationTheme.HighContrast){
    //High Contrast
}
if (FrameworkApplication.ApplicationTheme == ApplicationTheme.Default) {
    //Light/Default theme
}

Display a Pro MessageBox

ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Some Message", "Some title", MessageBoxButton.YesNo, MessageBoxImage.Information, MessageBoxResult.Yes);

Add a toast notification

Notification notification = new Notification();
notification.Title = FrameworkApplication.Title;
notification.Message = "Notification 1";
notification.ImageUrl = @"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/ToastLicensing32.png";

ArcGIS.Desktop.Framework.FrameworkApplication.AddNotification(notification);

Change a buttons caption or image

private void ChangeCaptionImage()
{
  IPlugInWrapper wrapper = FrameworkApplication.GetPlugInWrapper("MyAddin_MyCustomButton");
  if (wrapper != null)
  {
    wrapper.Caption = "new caption";

    // ensure that T-Rex16 and T-Rex32 are included in your add-in under the images folder and have 
    // BuildAction = Resource and Copy to OutputDirectory = Do not copy
    wrapper.SmallImage = BuildImage("T-Rex16.png");
    wrapper.LargeImage = BuildImage("T-Rex32.png");
  }
}

private ImageSource BuildImage(string imageName)
{
  return new BitmapImage(PackUriForResource(imageName));
}

private Uri PackUriForResource(string resourceName)
{
  string asm = System.IO.Path.GetFileNameWithoutExtension(
      System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
  return new Uri(string.Format("pack://application:,,,/{0};component/Images/{1}", asm, resourceName), UriKind.Absolute);
}

Subscribe to Active Tool Changed Event

private void SubscribeEvent()
{
  ArcGIS.Desktop.Framework.Events.ActiveToolChangedEvent.Subscribe(OnActiveToolChanged);
}
private void UnSubscribeEvent()
{
  ArcGIS.Desktop.Framework.Events.ActiveToolChangedEvent.Unsubscribe(OnActiveToolChanged);
}
private void OnActiveToolChanged(ArcGIS.Desktop.Framework.Events.ToolEventArgs args)
{
  string prevTool = args.PreviousID;
  string newTool = args.CurrentID;
}

Progressor - Simple and non-cancelable

public async Task Progressor_NonCancelable()
{
  ArcGIS.Desktop.Framework.Threading.Tasks.ProgressorSource ps = new ArcGIS.Desktop.Framework.Threading.Tasks.ProgressorSource("Doing my thing...", false);

  int numSecondsDelay = 5;
  //If you run this in the DEBUGGER you will NOT see the dialog
  await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => Task.Delay(numSecondsDelay * 1000).Wait(), ps.Progressor);
}

Progressor - Cancelable

public async Task Progressor_Cancelable()
{
  ArcGIS.Desktop.Framework.Threading.Tasks.CancelableProgressorSource cps = 
    new ArcGIS.Desktop.Framework.Threading.Tasks.CancelableProgressorSource("Doing my thing - cancelable", "Canceled");

  int numSecondsDelay = 5;
  //If you run this in the DEBUGGER you will NOT see the dialog

  //simulate doing some work which can be canceled
  await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => 
  {
      cps.Progressor.Max = (uint)numSecondsDelay;
      //check every second
      while (!cps.Progressor.CancellationToken.IsCancellationRequested) {
          cps.Progressor.Value += 1;
          cps.Progressor.Status = "Status " + cps.Progressor.Value;
          cps.Progressor.Message = "Message " + cps.Progressor.Value;

          if (System.Diagnostics.Debugger.IsAttached) {
              System.Diagnostics.Debug.WriteLine(string.Format("RunCancelableProgress Loop{0}", cps.Progressor.Value));
          }
          //are we done?
          if (cps.Progressor.Value == cps.Progressor.Max) break;
          //block the CIM for a second
          Task.Delay(1000).Wait();

      }
      System.Diagnostics.Debug.WriteLine(string.Format("RunCancelableProgress: Canceled {0}",
                                          cps.Progressor.CancellationToken.IsCancellationRequested));

  }, cps.Progressor);
}

Get an Image Resource from the Current Assembly

public static void ExampleUsage() {
    //Image 'Dino32.png' is added as Build Action: Resource, 'Do not copy'
    var img = ForImage("Dino32.png");
    //Use the image...
}

public static BitmapImage ForImage(string imageName) {
    return new BitmapImage(PackUriForResource(imageName));
}
public static Uri PackUriForResource(string resourceName, string folderName = "Images") {
    string asm = System.IO.Path.GetFileNameWithoutExtension(
        System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
    string uriString = folderName.Length > 0
        ? string.Format("pack://application:,,,/{0};component/{1}/{2}", asm, folderName, resourceName)
        : string.Format("pack://application:,,,/{0};component/{1}", asm, resourceName);
    return new Uri(uriString, UriKind.Absolute);
}

Prevent ArcGIS Pro from Closing

// There are two ways to prevent ArcGIS Pro from closing
// 1. Override the CanUnload method on your add-in's module and return false.
// 2. Subscribe to the ApplicationClosing event and cancel the event when you receive it

internal class Module1 : Module
{

  // Called by Framework when ArcGIS Pro is closing
  protected override bool CanUnload()
  {
    //return false to ~cancel~ Application close
    return false;
  }

  internal class Module2 : Module
  {
    public Module2()
    {
      ArcGIS.Desktop.Framework.Events.ApplicationClosingEvent.Subscribe(OnApplicationClosing);
    }
    ~Module2()
    {
      ArcGIS.Desktop.Framework.Events.ApplicationClosingEvent.Unsubscribe(OnApplicationClosing);
    }

    private Task OnApplicationClosing(System.ComponentModel.CancelEventArgs args)
    {
      args.Cancel = true;
      return Task.FromResult(0);
    }
  }
}

How to position an embeddable control inside a MapView

public ProSnippetMapTool()
{
    //Set the MapTool base class' OverlayControlID to the DAML id of your embeddable control in the constructor
    this.OverlayControlID = "ProAppModule1_EmbeddableControl1";
}

protected override void OnToolMouseDown(MapViewMouseButtonEventArgs e)
{
    if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
        e.Handled = true;
}

protected override Task HandleMouseDownAsync(MapViewMouseButtonEventArgs e)
{
    return QueuedTask.Run(() =>
    {
        //assign the screen coordinate clicked point to the MapTool base class' OverlayControlLocation property.
        this.OverlayControlLocation = e.ClientPoint;

    });
}

Start ArcGIS Pro from the command line

C:\>"C:\Program Files\ArcGIS Pro\bin\ArcGISPro.exe"

Get Command Line Arguments

If your Add-in requires the use of custom command line arguments your arguments must be of the form "/argument" - note the forward slash "/". There must be no white space. If the command line contains a project to be opened (see Open project from command line) then custom arguments or switches must be placed before the project filename argument.

   string[] args = System.Environment.GetCommandLineArgs();
   foreach (var arg in args)
   {
      // look for your command line switches
   }

Application Accelerators (Shortcut Keys)

Application accelerators can be added to your Add-in config.daml using an accelerators/insertAccelerator DAML element with the refID of the element to which you are associating the accelerator (i.e. short cut).

<accelerators>
    <insertAccelerator refID="esri_core_openProjectButton" flags="Ctrl" key="O" />
    <insertAccelerator refID="esri_core_redoButton" flags="Ctrl" key="Y" />
    <insertAccelerator refID="esri_core_undoButton" flags="Ctrl" key="Z" />
</accelerators>

Note: Use the deleteAccelerator and updateAccelerator DAML elements within an updateModule element to remove or alter application accelerators respectively. Flags can be one of: Shift, Ctrl, Alt, Ctrl+Shift, Alt+Shift, Ctrl+Alt, Ctrl+Alt+Shift

Defining controls in DAML with Pro Styles

There are many ArcGIS Pro styles defined which can be applied to buttons, labels and other controls on your panes and dockpanes to make your add-ins look and feel seamless with ArcGIS Pro. Some of the most common styles are listed below. For more styles and colors see the Styling-With-ArcGIS-Pro sample in the Community Samples repo.

Button styles

<Button Content="Button" Style="{StaticResource Esri_SimpleButton}" ToolTip="Button">
<Button Content="Button" Style="{StaticResource Esri_BackButton}" ToolTip="Button">
<Button Content="Button" Style="{StaticResource Esri_BackButtonSmall}" ToolTip="Button">
<Button Content="Button" Style="{StaticResource Esri_CloseButton}" ToolTip="Button">

Dockpane heading style

<TextBlock Text="MyDockPane" Style="{StaticResource DockPaneHeading}" 
                   VerticalAlignment="Center" HorizontalAlignment="Center"/>
Clone this wiki locally