-
Notifications
You must be signed in to change notification settings - Fork 117
ProGuide Dynamic Pop up Menu
Language: C# and Visual Basic
Subject: Map Exploration
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: Esri, http://www.esri.com
Date: 11/6/2017
ArcGIS Pro: 2.1
Visual Studio: 2015, 2017
This guide demonstrates how to create a map tool that uses a dynamic pop-up menu. You use the tool to select (by point click) a single feature on a map where multiple features overlap each other. See ProConcepts Map Exploration, MapTool for more information on the MapTool pattern.
Prerequisites
- Download and install the sample data required for this guide as instructed in Arcgis Pro SDK Community Samples Releases.
- Create a new ArcGIS Pro Module Add-in, and name the project MapToolWithDynamicMenu. If you are not familiar with the ArcGIS Pro SDK, you can follow the steps in the ProGuide Build your first add-in to get started.
- Add a new ArcGIS Pro Add-ins | ArcGIS Pro Map Tool item to the add-in project, and name the item MapToolShowMenu.
- There is no template to construct a dynamic pop-up menu, so you will construct the class from scratch in Step 1 and Step 3.
Step 1
Modify the Config.daml file tool item as follows:
- Change the caption to "Show Selection Pop-up".
- Change the tool heading to "Show Selection Pop-up" and the ToolTip text to "Click on overlapping point features on this map to pop-up a feature selection menu."
- Add a new dynamicMenu tag under the controls tag as shown below.
...
<tool id="MapToolWithDynamicMenu_MapToolShowMenu" caption="Show Selection Pop-up"
className="MapToolShowMenu" loadOnClick="true"
smallImage="Images\GenericButtonRed16.png"
largeImage="Images\GenericButtonRed32.png" condition="esri_mapping_mapPane" keytip="z2">
<tooltip heading="Show Selection Pop-up">
Click on overlapping point features on this map to pop-up a feature selection menu.
<disabledText />
</tooltip>
</tool>
<dynamicMenu id="DynamicMenu_SelectPoint"
className="DynamicSelectPointMenu"
caption="Point Selection" />
...
Build the sample and validate the UI on the ArcGIS Pro ribbon.
Step 2
The required selection functions must be implemented in the MapToolShowMenu class.
First, the sketch type set in the constructor is changed to SketchGeometryType.Point. Next, SketchOutputMode in the constructor is changed to SketchOutputMode.Screen. MapView.SelectFeatures and MapView.GetFeatures throw a System.ArgumentException if a 3D query is attempted in SketchOutputMode.Map, so you need to change the sketch projection to screen coordinates.
public MapToolShowMenu()
{
IsSketchTool = true;
SketchType = SketchGeometryType.Point;
SketchOutputMode = SketchOutputMode.Screen;
}
The OnSketchCompleteAsync method can be overwritten to implement the required selection functionality. Since you "await" functions within your identify implementation, you have to add the "async" keyword to the OnSketchCompleteAsync method declaration. The MapTool base class provides an ActiveMapView property that provides a link to the current active map view. The MapView, in turn, provides a method GetFeatures that can be used to get all features that intersect a given geometry. The resulting features are manipulated into a list of triple tuple objects consisting of BasicFeatureLayer Name, the Object ID field Name, and the object id. This list of triple tuples is then passed into ShowContextMenu, which creates and displays the dynamic pop-up menu.
protected override async Task<bool> OnSketchCompleteAsync(Geometry geometry)
{
var bottomRight = new Point();
IList<Tuple<string, string, long>> tripleTuplePoints =
new List<Tuple<string, string, long>>();
var hasSelection = await QueuedTask.Run(() =>
{
// geometry is a point
var clickedPnt = geometry as MapPoint;
if (clickedPnt == null) return false;
// pixel tolerance
var tolerance = 3;
//Get the client point edges
var topLeft = new Point(clickedPnt.X - tolerance, clickedPnt.Y + tolerance);
bottomRight = new Point(clickedPnt.X + tolerance, clickedPnt.Y - tolerance);
//convert the client points to Map points
var mapTopLeft = MapView.Active.ClientToMap(topLeft);
var mapBottomRight = MapView.Active.ClientToMap(bottomRight);
//create a geometry using these points
Geometry envelopeGeometry = EnvelopeBuilder.CreateEnvelope(mapTopLeft, mapBottomRight);
if (envelopeGeometry == null) return false;
//Get the features that intersect the sketch geometry.
var result = ActiveMapView.GetFeatures(geometry);
foreach (var kvp in result)
{
var bfl = kvp.Key;
// only look at points
if (kvp.Key.ShapeType != esriGeometryType.esriGeometryPoint) continue;
var layerName = bfl.Name;
var oidName = bfl.GetTable().GetDefinition().GetObjectIDField();
foreach (var oid in kvp.Value)
{
tripleTuplePoints.Add(new Tuple<string, string, long>(layerName, oidName, oid));
}
}
return true;
});
if (hasSelection)
{
ShowContextMenu(bottomRight, tripleTuplePoints);
}
return true;
}
Finally, you need to add a method that performs the actual display of the dynamic menu (with the Id DynamicMenu_SelectPoint specified in config.daml under the dynamicMenu tag). First, use the FrameworkApplication's CreateContextMenu method to create an instance of your DynamicMenu_SelectPoint pop-up menu. The resulting contextMenu object is of the type System.Windows.Controls.ContextMenu, and there are a few events and properties in this class that are noteworthy: contextMenu.Closed allows you to hook an event when the pop-up menu is closed, and the IsOpen property displays the pop-up menu when set to true. The class for DynamicMenu_SelectPoint is specified in the config.daml file as shown below in the className attribute:
<dynamicMenu id="DynamicMenu_SelectPoint" className="DynamicSelectPointMenu" ... />
Use a static method in DynamicSelectPointMenu called SetMenuPoints to pass the tripleTuplePoints (holding your selected feature record set) to the dynamic pop-up menu.
private void ShowContextMenu(System.Windows.Point screenLocation,
IList<Tuple<string, string, long>> tripleTuplePoints)
{
var contextMenu = FrameworkApplication.CreateContextMenu("DynamicMenu_SelectPoint",
() => screenLocation);
if (contextMenu == null) return;
DynamicSelectPointMenu.SetMenuPoints(tripleTuplePoints);
contextMenu.Closed += (o, e) =>
{
// nothing to do
System.Diagnostics.Debug.WriteLine(e);
};
contextMenu.IsOpen = true;
}
Step 3
Add the DynamicSelectPointMenu that handles the dynamic pop-up menu and the feature selection.
DynamicSelectPointMenu uses an image in its pop-up display. Add the image (use the file shown below) to the image folder of your project, name the image esri_PntFeature.png, and set the build action to Resource. As shown in the previous step, the static method in DynamicSelectPointMenu called SetMenuPoints is used to pass in the tripleTuplePoints (holding your selected feature record set), which are added as menu items in the OnPopup method.
internal class DynamicSelectPointMenu : DynamicMenu
{
internal delegate void ClickAction(Tuple<string, string, long> selectedTrippTuple);
private const string ImagePath =
@"pack://application:,,,/MapToolWithDynamicMenu;Component/Images/esri_PntFeature.png";
private static IList<Tuple<string, string, long>> _menuItems
= new List<Tuple<string, string, long>>();
public static void SetMenuPoints(IList<Tuple<string, string, long>> tripleTuples)
{
_menuItems = new List<Tuple<string, string, long>>(tripleTuples);
}
protected override void OnPopup()
{
if (_menuItems == null || _menuItems.Count == 0)
{
this.Add("No features found", "", false, true, true);
}
else
{
ClickAction theAction = OnMenuItemClicked;
Add("Select feature:", "", false, true, true);
foreach (var tuple in _menuItems)
{
var layer = tuple.Item1;
var oid = tuple.Item3;
Add($"{layer}: Id {oid}",
ImagePath,
false, true, false, theAction, tuple);
}
}
}
private static void OnMenuItemClicked(Tuple<string, string, long> selectedTrippTuple)
{
QueuedTask.Run(() =>
{
var mapView = MapView.Active;
var layers =
mapView.Map.GetLayersAsFlattenedList()
.Where(l => l.Name.Equals(selectedTrippTuple.Item1,
StringComparison.CurrentCultureIgnoreCase));
foreach (var featureLayer in layers.OfType<FeatureLayer>())
{
// select the features with a given OID
featureLayer.Select(new QueryFilter()
{
WhereClause = $@"{selectedTrippTuple.Item2} = {selectedTrippTuple.Item3}"
});
break;
}
});
}
}
Step 4
Rebuild the add-in. Fix any compilation errors.
Step 5
Debug the add-in. Run the debugger and start ArcGIS Pro. Open the C:\Data\Interacting with Maps\Interacting with Maps.aprx project that contains a dataset that works with this sample. Try the selection tool over a map area with a high point feature density as shown here:
Home | API Reference | Requirements | Download | Samples
- Overview of the ArcGIS Pro SDK
- What's New for Developers at 3.4
- Installing ArcGIS Pro SDK for .NET
- Release notes
- Resources
- Pro SDK Videos
- ProSnippets
- ArcGIS Pro API
- ProGuide: ArcGIS Pro Extensions NuGet
Migration
- ProSnippets: Framework
- ProSnippets: DAML
- ProConcepts: Framework
- ProConcepts: Asynchronous Programming in ArcGIS Pro
- ProConcepts: Advanced topics
- ProGuide: Custom settings
- ProGuide: Command line switches for ArcGISPro.exe
- ProGuide: Reusing ArcGIS Pro Commands
- ProGuide: Licensing
- ProGuide: Digital signatures
- ProGuide: Command Search
- ProGuide: Keyboard shortcuts
Add-ins
- ProGuide: Installation and Upgrade
- ProGuide: Your first add-in
- ProGuide: ArcGIS AllSource Project Template
- ProConcepts: Localization
- ProGuide: Content and Image Resources
- ProGuide: Embedding Toolboxes
- ProGuide: Diagnosing ArcGIS Pro Add-ins
- ProGuide: Regression Testing
Configurations
Customization
- ProGuide: The Ribbon, Tabs and Groups
- ProGuide: Buttons
- ProGuide: Label Controls
- ProGuide: Checkboxes
- ProGuide: Edit Boxes
- ProGuide: Combo Boxes
- ProGuide: Context Menus
- ProGuide: Palettes and Split Buttons
- ProGuide: Galleries
- ProGuide: Dockpanes
- ProGuide: Code Your Own States and Conditions
Styling
- ProSnippets: Content
- ProSnippets: Browse Dialog Filters
- ProConcepts: Project Content and Items
- ProConcepts: Custom Items
- ProGuide: Custom Items
- ProGuide: Custom browse dialog filters
- ArcGIS Pro TypeID Reference
- ProSnippets: Editing
- ProConcepts: Editing
- ProConcepts: COGO
- ProConcepts: Annotation Editing
- ProConcepts: Dimension Editing
- ProGuide: Editing Tool
- ProGuide: Sketch Tool With Halo
- ProGuide: Construction Tools with Options
- ProGuide: Annotation Construction Tools
- ProGuide: Annotation Editing Tools
- ProGuide: Knowledge Graph Construction Tools
- ProGuide: Templates
3D Analyst Data
Plugin Datasources
Topology
Linear Referencing
Object Model Diagram
- ProSnippets: Geometry
- ProSnippets: Geometry Engine
- ProConcepts: Geometry
- ProConcepts: Multipatches
- ProGuide: Building Multipatches
Relational Operations
- ProSnippets: Knowledge Graph
- ProConcepts: Knowledge Graph
- ProGuide: Knowledge Graph Construction Tools
Reports
- ProSnippets: Map Authoring
- ProSnippets: Annotation
- ProSnippets: Charts
- ProSnippets: Labeling
- ProSnippets: Renderers
- ProSnippets: Symbology
- ProSnippets: Text Symbols
- ProConcepts: Map Authoring
- ProConcepts: Annotation
- ProConcepts: Dimensions
- ProGuide: Tray buttons
- ProGuide: Custom Dictionary Style
- ProGuide: Geocoding
3D Analyst
CIM
Graphics
Scene
Stream
Voxel
- ProSnippets: Map Exploration
- ProSnippets: Custom Pane with Contents
- ProConcepts: Map Exploration
- ProGuide: Map Pane Impersonation
- ProGuide: TableControl
Map Tools
- ProGuide: Feature Selection
- ProGuide: Identify
- ProGuide: MapView Interaction
- ProGuide: Embeddable Controls
- ProGuide: Custom Pop-ups
- ProGuide: Dynamic Pop-up Menu
Network Diagrams
- ArcGIS Pro API Reference Guide
- ArcGIS Pro SDK (pro.arcgis.com)
- arcgis-pro-sdk-community-samples
- ArcGISPro Registry Keys
- ArcGIS Pro DAML ID Reference
- ArcGIS Pro Icon Reference
- ArcGIS Pro TypeID Reference
- ProConcepts: Distributing Add-Ins Online
- ProConcepts: Migrating to ArcGIS Pro
- FAQ
- Archived ArcGIS Pro API Reference Guides
- Dev Summit Tech Sessions