-
Notifications
You must be signed in to change notification settings - Fork 119
ProSnippets Framework
Language: C#
Subject: Framework
Contributor: ArcGIS Pro SDK Team <arcgisprosdk@esri.com>
Organization: esri, http://www.esri.com
Date: 10/22/2024
ArcGIS Pro: 3.4
Visual Studio: 2022
.NET Target Framework: .Net 8
private SubscriptionToken _eventToken = null;
// Called when the visibility of the DockPane changes.
protected override void OnShow(bool isVisible)
{
if (isVisible && _eventToken == null) //Subscribe to event when dockpane is visible
{
_eventToken = MapSelectionChangedEvent.Subscribe(OnMapSelectionChangedEvent);
}
if (!isVisible && _eventToken != null) //Unsubscribe as the dockpane closes.
{
MapSelectionChangedEvent.Unsubscribe(_eventToken);
_eventToken = null;
}
}
//Event handler when the MapSelection event is triggered.
private void OnMapSelectionChangedEvent(MapSelectionChangedEventArgs obj)
{
MessageBox.Show("Selection has changed");
}
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);
// 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);
FrameworkApplication.ActivateTab("esri_mapping_insertTab");
// Define the condition in the DAML file based on the state
if (activate)
FrameworkApplication.State.Activate("someState");
else
FrameworkApplication.State.Deactivate("someState");
// 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;
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;
FrameworkApplication.Close();
//"GetEntryAssembly" should be ArcGISPro.exe
string version = System.Reflection.Assembly.GetEntryAssembly()
.GetName().Version.ToString();
string _viewPaneID = "my pane"; //DAML ID of your pane
//You could have multiple instances (InstanceIDs) of your pane.
//So you can iterate through the Panes to get "your" panes only
IList<uint> myPaneInstanceIDs = new List<uint>();
foreach (Pane pane in FrameworkApplication.Panes)
{
if (pane.ContentID == _viewPaneID)
{
myPaneInstanceIDs.Add(pane.InstanceID); //InstanceID of your pane, could be multiple, so build the collection
}
}
foreach (var instanceID in myPaneInstanceIDs) //close each of "your" panes.
{
FrameworkApplication.Panes.ClosePane(instanceID);
}
var mapPanes = ProApp.Panes.OfType<IMapPane>();
foreach (Pane pane in mapPanes)
{
if (pane.Caption == "MyMap")
{
pane.Activate();
break;
}
}
ProWindow1 _prowindow1 = null;
{
double left = 150; //Window's left edge, in relation to the desktop
double top = 150; //Window's top edge, in relation to the desktop
//already open?
if (_prowindow1 != null)
return;
_prowindow1 = new ProWindow1(left, top); //create window
_prowindow1.Owner = FrameworkApplication.Current.MainWindow;
_prowindow1.Closed += (o, e) => { _prowindow1 = null; };
//MetroWindows remember their last location unless SaveWindowPosition is set to
//false.
_prowindow1.SaveWindowPosition = false; //set to false to override the last position
_prowindow1.Show();
//uncomment for modal
//_prowindow1.ShowDialog();
}
var addin_infos = FrameworkApplication.GetAddInInfos();
StringBuilder sb = new StringBuilder();
foreach (var info in addin_infos)
{
if (info == null)
break;//no addins probed
sb.AppendLine($"Addin: {info.Name}");
sb.AppendLine($"Description {info.Description}");
sb.AppendLine($"ImagePath {info.ImagePath}");
sb.AppendLine($"Author {info.Author}");
sb.AppendLine($"Company {info.Company}");
sb.AppendLine($"Date {info.Date}");
sb.AppendLine($"Version {info.Version}");
sb.AppendLine($"FullPath {info.FullPath}");
sb.AppendLine($"DigitalSignature {info.DigitalSignature}");
sb.AppendLine($"IsCompatible {info.IsCompatible}");
sb.AppendLine($"IsDeleted {info.IsDeleted}");
sb.AppendLine($"TargetVersion {info.TargetVersion}");
sb.AppendLine($"ErrorMsg {info.ErrorMsg}");
sb.AppendLine($"ID {info.ID}");
sb.AppendLine("");
}
System.Diagnostics.Debug.WriteLine(sb.ToString());
MessageBox.Show(sb.ToString(), "Addin Infos");
// in order to find a dockpane you need to know it's DAML id
var pane = FrameworkApplication.DockPaneManager.Find("esri_core_ProjectDockPane");
// 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();
// 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");
}
// 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;
//Opens the Backstage to the "About ArcGIS Pro" tab.
FrameworkApplication.OpenBackstage("esri_core_aboutTab");
//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
}
ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show("Some Message", "Some title", MessageBoxButton.YesNo, MessageBoxImage.Information, MessageBoxResult.Yes);
Notification notification = new Notification();
notification.Title = FrameworkApplication.Title;
notification.Message = "Notification 1";
notification.ImageSource = System.Windows.Application.Current.Resources["ToastLicensing32"] as ImageSource;
ArcGIS.Desktop.Framework.FrameworkApplication.AddNotification(notification);
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().Location);
return new Uri(string.Format("pack://application:,,,/{0};component/Images/{1}", asm, resourceName), UriKind.Absolute);
}
//Pass in the daml id of your button. Or pass in any Pro button ID.
IPlugInWrapper wrapper = FrameworkApplication.GetPlugInWrapper("button_id_from daml");
var buttonTooltipHeading = wrapper.TooltipHeading;
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;
}
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);
}
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);
}
//Set the tool's loadOnClick attribute to "false" in the config.daml.
//This will allow the tool to be created when Pro launches, so that the disabledText property can display customized text at startup.
//Remove the "condition" attribute from the tool. Use the OnUpdate method(below) to set the enable\disable state of the tool.
//Add the OnUpdate method to the tool.
//Note: since OnUpdate is called very frequently, you should avoid lengthy operations in this method
//as this would reduce the responsiveness of the application user interface.
internal class SnippetButton : ArcGIS.Desktop.Framework.Contracts.Button
{
protected override void OnUpdate()
{
bool enableSate = true; //TODO: Code your enabled state
bool criteria = true; //TODO: Evaluate criteria for disabledText
if (enableSate)
{
this.Enabled = true; //tool is enabled
}
else
{
this.Enabled = false; //tool is disabled
//customize your disabledText here
if (criteria)
this.DisabledTooltip = "Missing criteria 1";
}
}
}
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().Location);
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);
}
// 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);
}
// cref: ARCGIS.DESKTOP.CORE.EVENTS.PROJECTOPENEDEVENT
// cref: ARCGIS.DESKTOP.CORE.EVENTS.PROJECTOPENEDEVENT.SUBSCRIBE
// cref: ARCGIS.DESKTOP.CORE.EVENTS.PROJECTOPENEDEVENT.UNSUBSCRIBE
// cref: ARCGIS.DESKTOP.FRAMEWORK.CONTRACTS.MODULE.INITIALIZE
// cref: ARCGIS.DESKTOP.FRAMEWORK.CONTRACTS.MODULE.UNINITIALIZE
#region How to determine when a project is opened
protected override bool Initialize() //Called when the Module is initialized.
{
ProjectOpenedEvent.Subscribe(OnProjectOpened); //subscribe to Project opened event
return base.Initialize();
}
private void OnProjectOpened(ProjectEventArgs obj) //Project Opened event handler
{
MessageBox.Show($"{Project.Current} has opened"); //show your message box
}
protected override void Uninitialize() //unsubscribe to the project opened event
{
ProjectOpenedEvent.Unsubscribe(OnProjectOpened); //unsubscribe
return;
}
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.OverlayControlPositionRatio = e.ClientPoint;
});
}
//In the module class..
public override string[] GetSuggestedCMDIDs(string activeTabID)
{
//Return the static list of daml ids you want to be the (suggested)
//defaults relevant to the given tab. It can be none, some, or all of the
//commands associated with the activeTabID.
//In this example, there are two tabs. This example arbitrarily
//identifies just one command on each tab to be a default to show in the
//command search list (when _that_ particular tab is active)
switch (activeTabID)
{
case "CommandSearch_Example_Tab1":
return new string[] { "CommandSearch_Example_Button2" };
case "CommandSearch_Example_Tab2":
return new string[] { "CommandSearch_Example_Button4" };
}
return new string[] { "" };
}
C:\>"C:\Program Files\ArcGIS Pro\bin\ArcGISPro.exe"
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 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
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"/>
Home | API Reference | Requirements | Download | Samples
-
Subscribe and unsubscribe to events when the dockpane is visible or hidden
-
Execute a command
-
Set the current tool
-
Activate a tab
-
Activate/Deactivate a state - to modify a condition
-
Determine if the application is busy
-
Get the Application main window
-
Close ArcGIS Pro
-
Get ArcGIS Pro version
-
Close a specific pane
-
Activate a pane
-
ProWindow Position on Screen
-
Get Information on the Currently Installed Add-ins
-
Find a dockpane
-
Dockpane properties and methods
-
Dockpane undo / redo
-
Find a dockpane and obtain its ViewModel
-
Open the Backstage tab
-
Access the current theme
-
Display a Pro MessageBox
-
Add a toast notification
-
Change a buttons caption or image
-
Get a button's tooltip heading
-
Subscribe to Active Tool Changed Event
-
Progressor - Simple and non-cancelable
-
Progressor - Cancelable
-
Customize the disabedText property of a button or tool
-
Get an Image Resource from the Current Assembly
-
Prevent ArcGIS Pro from Closing
-
Position an embeddable control inside a MapView
-
Suggested command options in CommandSearch when a tab is activated.
-
Start ArcGIS Pro from the command line
-
Get Command Line Arguments
-
Application Accelerators (Shortcut Keys)
-
Defining controls in DAML with Pro Styles