Select to view content in your preferred language

Using conditions in config.daml to enable/disable add-in

576
5
Jump to solution
02-20-2025 09:49 AM
RichardDaniels
Honored Contributor

I have an add-in that Should be enabled by default when my custom tab is open and there is an Active map. I would like to be able to programmatically disable the tool if there is an error (in my case I need to connect to a remote large feature class and want to disable the tool if the FC is unavailable or unreachable).

 As discussed in the documentation I've added a <conditions> tag after </AddInInfo> and a condition attributed to my <tool> but when I add the condition my tool is always disabled on first load.

 

Here is the condition:

 <conditions>
    <insertCondition id="srview_condition">
      <state id="srview_state" />
    </insertCondition>
  </conditions>
 
      <controls>
        <!-- add your controls here -->
        <tool id="SRView4Pro_modSRView4Pro" caption="SR View for Pro" className="SRView4ProTool" keytip="T3" loadOnClick="true" smallImage="Images\SRViewButton16.png" largeImage="Images\SRViewButton32.png" condition="srview_condition">
          <tooltip heading="SR View for Pro">Show SR View 3 images or Google StreetView from left mouse click.<disabledText /></tooltip>
        </tool>
      </controls>
 
It looks like the condition is being set to Deactivated by default so the tool is never available to be run. In the Initialize event I added .Activate but I don't think this Event is actually RUN. Ideas? Code Attached.
0 Kudos
2 Solutions

Accepted Solutions
RichardDaniels
Honored Contributor

I had it set to false because Add-In loading can add +30 seconds to ArcGIS Pro startup. I resolved this by moving my long running code into an if block and introducing a first use check. This allowed me to set autoLoad="true" as recommended.

private bool firstUse = true;

protected override Task OnToolActivateAsync(bool active)
{
if (firstUse==true)
      {  // do long running work only Once!

    firstUse = false;

     }

return base.OnToolActivateAsync(active);
}

View solution in original post

0 Kudos
RichardDaniels
Honored Contributor

Solution: As suggested I changed load autoLoad="true" in my Module in the config.daml. I moved my long running task into the OnToolActivateAsync event with wrapper code to ensure it only is run the 1st time the button/Tool is clicked on the Ribbon. I Activate the tool with FrameworkApplication.State.Activate in the initial class constructor and setup a new event handler to 'catch' all UI codes that are not caught explicitly within the application this (1) protects ArcGIS Pro itself from crashing and (2) allows me to do .Deactivate if the add-in has an unhandled error.

In the modules class,  defined in the config.daml as SRView4ProTool, I update the constructor as follows and configured the data handler.

 

public SRView4ProTool()
{
if (getEnterpriseTableConnection() == null) //if this is null then this is the first time clicked on the add-in during the session, this could just be a public static int runCount but I'm using my data connection that was setup in OnToolActivateAsync
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandler_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go throughour handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//set the state
FrameworkApplication.State.Activate("srview_state");
}

IsSketchTool = true;
SketchType = SketchGeometryType.Point;
SketchOutputMode = SketchOutputMode.Map;
}

I then add the event handler code

private static void ErrorHandler_UIThreadException(object sendor, ThreadExceptionEventArgs t)
{
DialogResult result = DialogResult.Cancel;
result = MessageBox.Show("Fatal Windows Form Error. Would you like to try to continue OR Cancel/Close the Add-In?",
"Fatal Windows Forms Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Stop);
// Exits the program when the user clicks Cancel.
if (result == DialogResult.Cancel)
  {
  formResults.btnClose_Click(sendor, t);
  FrameworkApplication.State.Deactivate("srview_state");
  }
}

View solution in original post

0 Kudos
5 Replies
KenBuja
MVP Esteemed Contributor

Did you set autoLoad to true in the module?

...
  <modules>
    <insertModule id="ConditionsAndStates_Module" className="Module1" 
	              autoLoad="true" caption="Module1">
...

 

0 Kudos
RichardDaniels
Honored Contributor

I had it set to false because Add-In loading can add +30 seconds to ArcGIS Pro startup. I resolved this by moving my long running code into an if block and introducing a first use check. This allowed me to set autoLoad="true" as recommended.

private bool firstUse = true;

protected override Task OnToolActivateAsync(bool active)
{
if (firstUse==true)
      {  // do long running work only Once!

    firstUse = false;

     }

return base.OnToolActivateAsync(active);
}

0 Kudos
SelimDissem
Esri Contributor

@RichardDaniels

One thing to know is that conditions are shared across all add-ins so you could define and implement the condition on a "fast loading" add-in with autoLoad="true" whose only role would be to determine if the "bigger/slow loading" add-in should be enabled or not and sets the state to the appropriate value.

That way, you also keep the changes to your existing add-in to the condition specification in the DAML while the coding is in the "lighter" add-in.

On a separate note, you could look into the performance of your main add-in and ways to improve it - it shouldn't be delaying ArcGIS Pro startup by 30s. You could also visit the Pro SDK team at the showcase of one of our Esri conferences (Dev Summit, User Conference) to check with us for any performance improvement tips.

RichardDaniels
Honored Contributor

The add-in connects to a SQL Feature Class with about 1,232,000 points using Geodatabase.OpenDataset<Table>  on startup. This is done on the load event to ensure it only happens once (not each time the tool is clicked on the ribbon).

0 Kudos
RichardDaniels
Honored Contributor

Solution: As suggested I changed load autoLoad="true" in my Module in the config.daml. I moved my long running task into the OnToolActivateAsync event with wrapper code to ensure it only is run the 1st time the button/Tool is clicked on the Ribbon. I Activate the tool with FrameworkApplication.State.Activate in the initial class constructor and setup a new event handler to 'catch' all UI codes that are not caught explicitly within the application this (1) protects ArcGIS Pro itself from crashing and (2) allows me to do .Deactivate if the add-in has an unhandled error.

In the modules class,  defined in the config.daml as SRView4ProTool, I update the constructor as follows and configured the data handler.

 

public SRView4ProTool()
{
if (getEnterpriseTableConnection() == null) //if this is null then this is the first time clicked on the add-in during the session, this could just be a public static int runCount but I'm using my data connection that was setup in OnToolActivateAsync
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new ThreadExceptionEventHandler(ErrorHandler_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go throughour handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//set the state
FrameworkApplication.State.Activate("srview_state");
}

IsSketchTool = true;
SketchType = SketchGeometryType.Point;
SketchOutputMode = SketchOutputMode.Map;
}

I then add the event handler code

private static void ErrorHandler_UIThreadException(object sendor, ThreadExceptionEventArgs t)
{
DialogResult result = DialogResult.Cancel;
result = MessageBox.Show("Fatal Windows Form Error. Would you like to try to continue OR Cancel/Close the Add-In?",
"Fatal Windows Forms Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Stop);
// Exits the program when the user clicks Cancel.
if (result == DialogResult.Cancel)
  {
  formResults.btnClose_Click(sendor, t);
  FrameworkApplication.State.Deactivate("srview_state");
  }
}

0 Kudos