ContextMenuDataContext is null with Module CanClick handler method

450
3
04-16-2020 08:40 PM
KirkKuykendall2
Occasional Contributor

I've configured a button to appear on the layer context menu, so that it calls CopyUVRToStyle on the module, which it does successfully and examines ContextMenuDataContext without any issues.

However ... when it accesses the CanCopyUVRToStyle property, ContextMenuDataContext is always null.

The documentation suggests keeping an _enabled variable. 

ProConcepts Framework · Esri/arcgis-pro-sdk Wiki · GitHub 

Is there an event that fires somewhere (like OnContextMenu?) that the module can subscribe to and examine the ContextMenuDataContext and set the _enabled variable accordingly?

https://github.com/Esri/arcgis-pro-sdk/wiki/ProConcepts-Framework#delegate-commands

Tags (2)
0 Kudos
3 Replies
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Your finding is correct ContextMenuDataContext  is null for the Can method for DelegateCommands.  I will check with the development team on this issue.  However, if you intend to use this function to control visibility of your menu button i would recommend to use a condition instead.

When i duplicated your issue i was only interested in showing the context menu button when a feature layer has been selected.  So i added the esri_mapping_featureLayerSelectedCondition condition to my button:

<controls>
  <!-- add your controls here -->
  <button id="TestContextMenu_LayerContextMenu_Items_Button1" caption="Show Selected FLyr Name"
          className="TestContextMenu_Module:OnMenuButtonClick" loadOnClick="true" keytip="B1"
          condition="esri_mapping_featureLayerSelectedCondition"
          smallImage="Images/GenericButtonGreen16.png" 
          largeImage="Images/GenericButtonGreen32.png">
    <tooltip heading="Menu Button 1">ToolTip<disabledText /></tooltip>
  </button>
</controls>‍‍‍‍‍‍‍‍‍‍

And now the context menu honors the state of condition i added:  Below is the context menu when a feature layer has been selected:

and here is context menu when a raster layer has been selected:

You can find more conditions here:  https://github.com/Esri/arcgis-pro-sdk/wiki/DAML-ID-Reference-ADMapping.daml#conditions

KirkKuykendall2
Occasional Contributor

Thanks Wolfgang, this is helpful.  I'd like to further constrain it so that it's only enabled when a featurelayer has a UniqueValueRenderer.

I don't see a condition for this.  For now I can just pop up a messagebox saying "choose a layer with UVR".

More generally, in the long run I think it would be useful for there to be an OnContextMenu event.

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

You can create you own state & condition for this.  Make the following changes to your config.daml:

Add the following before the <modules> tag:

  <conditions>
    <insertCondition id="has_UVR_Condition" caption="Feature Layer with UVR">
      <state id="has_UVR_State" />
    </insertCondition>
  </conditions>

set the <insertModule tag's attribute: autoLoad to true:

<insertModule id="TestContextMenu_Module" className="Module1" autoLoad="true"

Change you button's condition to the new "has_UVR_Condition":

<button id="TestContextMenu_LayerContextMenu_Items_Button1" 
        caption="Show Selected FeatLyr Name"
        className="TestContextMenu_Module:OnMenuButtonClick" 
        loadOnClick="true" keytip="B1"
        condition="has_UVR_Condition"
        ...

and finally add this code to Module1.cs:

    internal Module1()
    {
      TOCSelectionChangedEvent.Subscribe(CheckRenderer);
    }

    /// <summary>
    /// This method makes sure
    /// 1. The Mapview is Active
    /// 2. There is exactly one layer selected
    /// 3. The selected Layer is a FeatureLayer
    /// 4. The feature layer's rendered is a unique value renderer
    /// then sets the state for has_UVR_State & condition
    /// </summary>
    /// <param name="mapViewEventArgs"></param>
    private async void CheckRenderer(MapViewEventArgs mapViewEventArgs)
    {
      if (mapViewEventArgs.MapView == null || (
          mapViewEventArgs.MapView.GetSelectedLayers().Count != 1 ||
          !(mapViewEventArgs.MapView.GetSelectedLayers()[0] is FeatureLayer)))
      {
        SetState("has_UVR_State", false);
        return;
      }
      var bFeatLry = mapViewEventArgs.MapView.GetSelectedLayers()[0] as FeatureLayer;
      SetState ("has_UVR_State", await QueuedTask.Run (() => bFeatLry.GetRenderer() is CIMUniqueValueRenderer));
    }

    internal static void SetState(string stateName, bool active)
    {
      if (FrameworkApplication.State.Contains(stateName) == active) return;
      // toggle the state
      if (FrameworkApplication.State.Contains(stateName))
      {
        //deactivates the state
        FrameworkApplication.State.Deactivate(stateName);
      }
      else
      {
        //activates the state
        FrameworkApplication.State.Activate(stateName);
      }
    }
0 Kudos