ProSnippets Framework - EsriJapan/arcgis-pro-sdk GitHub Wiki

Language:              C#  
Subject:               Framework  
Contributor:           ArcGIS Pro SDK Team <[email protected]>  
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;

ArcGIS Proを閉じる

FrameworkApplication.Close();

ArcGIS Pro のバージョンを取得

//"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;
  }
}

画面上の ProWindow の位置

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();

ドッキングペインの 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");
}

ドッキングペインを 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;

バックステージのタブを開く

//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 Pro メッセージボックスを表示

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;

アクティブなツールの Changed イベントをサブスクライブ

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);
}

ボタンとツールの disabedText プロパティのカスタマイズ

//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);
}

ArcGIS Pro を閉じる操作のキャンセル

// 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;
    }

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.OverlayControlPositionRatio = e.ClientPoint;

  });
}

タブのアクティブ化時の CommandSearch で推奨されるコマンド オプション

//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[] { "" };
}

コマンド ラインから ArcGIS Pro を起動

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

コマンド ライン引数の取得

アドインでカスタム コマンド ライン引数を使用する必要がある場合、引数は「/argument」の形式で入力する必要があります。スラッシュ「/」にスペースが含まれないよう注意してください。コマンド ラインからプロジェクトを開く場合、カスタム引数またはスイッチをプロジェクトファイル名の引数の前に配置する必要があります。

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

アプリケーション アクセラレータ (ショートカットキー)

アプリケーション アクセラレータは、accelerators / insertAccelerator DAML要素とアクセラレータを関連付ける要素の refID (ショートカット) を使用して、アドインの config.daml に追加できます。

<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>

注記:updateModule 要素内の deleteAccelerator / updateAccelerator DAML要素を使用して、アプリケーション アクセラレータを削除または変更します。フラグは、Shift、Ctrl、Alt、Ctrl + Shift、Alt + Shift、Ctrl + Alt、Ctrl + Alt + Shift のいずれかです。

Pro Styles を使用した DAML でのコントロールの定義

ArcGIS Pro には多くのスタイルが定義されており、ペインやドッキング ペインのボタン、ラベル、その他のコントロールに適用することで、アドインの外観や操作性を ArcGIS Pro とシームレスにすることができます。最も一般的なスタイルのいくつかを以下に示します。その他のスタイルと色については、CommunitySamples リポジトリのStyling-With-ArcGIS-Pro サンプルを参照してください。

ボタン スタイル

<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">

ドッキングペインのヘディング スタイル

<TextBlock Text="MyDockPane" Style="{StaticResource DockPaneHeading}" 
                   VerticalAlignment="Center" HorizontalAlignment="Center"/>
⚠️ **GitHub.com Fallback** ⚠️