ProGuide Code Your Own States and Conditions - Esri/arcgis-pro-sdk GitHub Wiki

This guide demonstrates how to code your own custom states and conditions.

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

Background

If you want a refresher or need help on how to build an add-in, read ProGuide: Build Your 1st Add-in.

States and Conditions

ArcGIS Pro incorporates a mechanism for activating and deactivating customizations based on user defined conditions. This binding between condition and customizations is provided using DAM and provides a simple way for expressing when various GUI elements such as ribbon tabs, dock panes, buttons and tools should and shouldn’t be enabled within the application.

Condition: Conditions are DAML expressions composed of one or more states, such as (A or B), where both A and B are states. Conditions themselves are named so that they can be referenced by DAML elements which permit the use of conditions; for instance, a custom ribbon tab can be caused to show up on the ribbon only when a map view is active, and hide when any other type of view is active.

State: States are named Boolean values which symbolize a particular aspect of the application’s overall status; for example, whether a particular view is active, or whether a particular type of feature is selected.

States and Conditions are declared using DAML elements as follows:

A simple condition (consisting of only one state):

<conditions>
  <insertCondition id="aSimpleCondition">
     <state id="someState"/>
  </insertCondition>
</conditions>

A more complex condition:

<conditions>
  <insertCondition id="aMoreComplexCondition">
    <and>
      <state id="someState"/>
        <or>
          <state id="someOtherState"/>
          <state id="yetAnotherState"/>
        </or>
    </and>
  </insertCondition>
</conditions>

The above condition evaluates to (someState AND (someOtherState OR yetAnotherState)).

Conditions are defined at the root level in the DAML file—outside the scope of any module block—since they are simply expressions (without an active aspect), and do not need to be associated with any controlling extension; conditions should be considered global in scope. The Boolean operators And, Or, and Not can be combined recursively to form complex conditional expressions if necessary.

Conditions are associated with a particular Plugin using the Condition attribute:

The specified custom button is enabled only when the condition is true

<button id="myButton" caption="Respond to state" 
        className="RespondToStateButton" loadOnClick="true" 
		smallImage="Images\GenericButtonBlack16.png"
		largeImage="Images\GenericButtonBlack32.png"
		condition="myCondition">
</button>

The states are activated or deactivated using the following API methods

  FrameworkApplication.State.Deactivate(stateID);
  FrameworkApplication.State.Activate(stateID);

Creating States and Conditions

There are three basic steps to creating and using states and conditions.

  1. Define the condition (based on a state or combination of states) or use an existing Esri Defined Condition
  2. Create a method or property to toggle the state
  3. Link the condition to a UI element

Use the method or property created in step 2 to modify the state value in response to some application change. This forces the condition to be re-evaluated and the UI to update.

Assume you have an add-in that contains two buttons on the UI. The first is a toggle button that controls the status of the state. The second button responds to the state through a condition.

Step 1: Define the condition

Define the condition in the DAML. Remember that conditions live outside the module tags. Our condition depends on a single state - "example_state". When it is true the condition will be true. When it is false the condition will be false.

  <conditions>
    <!-- our custom condition -->
    <insertCondition id="example_state_condition" caption="Example state">
      <!-- our condition is set true or false based on this underlying state -->
      <state id="example_state" />
    </insertCondition>
  </conditions>

Note: Set autoLoad = true if your Module needs to evaluate the initial condition (true, false) at startup.

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

More complex conditions can be constructed that apply boolean operators such as "and", "not", "or" to its underlying states. To see examples, examine the Pro daml files and search for conditions. For example ADCore.daml.xml

Step 2: Create a method to toggle the state

#region Toggle State
/// <summary>
/// Activate or Deactivate the specified state. State is identified via
/// its name. Listen for state changes via the DAML <b>condition</b> attribute
/// </summary>
/// <param name="stateID"></param>
public static void ToggleState(string stateID) 
{
   if (FrameworkApplication.State.Contains(stateID)) 
   {
      FrameworkApplication.State.Deactivate(stateID);
   } 
   else 
   {
      FrameworkApplication.State.Activate(stateID);
   }
}

#endregion Toggle State

Step 3: Link the condition to a UI element

In this instance, the condition is linked to a button on the ribbon.

<!-- associate our condition with the enabled state of the button 
     via the "condition" attribute -->
<button id="esri_sdk_RespondToAppStateBtn" caption="Respond to state" 
        className="RespondToStateButton" loadOnClick="true" 
		smallImage="Images\GenericButtonBlack16.png"
		largeImage="Images\GenericButtonBlack32.png"
		condition="example_state_condition">
   <tooltip heading="Respond To State Button">
        Listens for the condition named <b>example_state_condition</b>
	 <disabledText>The <b>example_state_condition</b> is False
	 </disabledText>
   </tooltip>
</button>

In this example, modifying the state value is achieved through an additional button whose OnClick event calls the ToggleState method with the example_state parameter.


Using Esri Defined Conditions

It is possible to build complex conditions based off of a number of states. For example

<insertCondition id="myCondition" caption="My Condition">
   <or>
      <state id="state1"/>
      <state id="state2"/>
   </or>
</insertCondition>

<insertCondition id="myCondition2" caption="My Condition 2">
   <and>
      <not>
         <state id="state1"/>
      </not>
      <not>
         <state id="state3"/>
      </not>
   </and>
</insertCondition>

You can use your own states or any of the Esri defined states in your conditions.

To use Esri defined conditions, you need to determine their state definition. You can accomplish this by searching for the condition in the appropriate module daml file. For example esri_mapping_xxx condition can be found in the (install_folder)\bin\Extensions\Mapping\ADMapping.daml file. However, the ArcGIS Pro DAML ID Reference wiki page provides you links to all DAML entries in all the public extensions online if you prefer.

Note: There are some special Esri conditions - such as esri_mapping_mapPane and esri_mapping_layoutPane that are based off pane ids. In this way, a condition can be set true or false depending on whether or not a given view type is active or not.

⚠️ **GitHub.com Fallback** ⚠️