ProConcepts Map Exploration - kataya/arcgis-pro-sdk GitHub Wiki
The mapping functionality in ArcGIS Pro is delivered through the ArcGIS.Desktop.Mapping assembly. Map Exploration provides classes and members that support navigating and interacting with views of a map. This includes modifying the view's extent by zooming to layers, features, and bookmarks, and interactively selecting or returning features that intersect a given sketch geometry.
- ArcGIS.Desktop.Mapping.dll
- ArcGIS.Desktop.Extensions.dll
Language: C#
Subject: Map Exploration
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: Esri, http://www.esri.com
Date: 11/24/2020
ArcGIS Pro: 2.7
Visual Studio: 2017, 2019
- MapView
- Camera
- MapTool
- Animation
- MapControl
- TableControl
- MapView Graphic Overlay
- MapView Overlay Control
A project can contain multiple maps, either 2D or 3D, and each defines the collection of layers that make up that map. A map view is simply a view of a map. Map views are the primary interface used to display, navigate, select, identify, and edit data in a 2D or 3D map. The MapView class provides properties and methods to navigate and interact with layers in the map. The map being visualized in the view can be accessed via the Map property.
There can be multiple map views open at a given time, but there can only be one active map view. The active map view will set the context for the ribbon and many of the dock panes in the application. For example, the map Contents pane will reflect the layers of the active map view's map. The instance of the active map view can be accessed via the static Active property on MapView. The active property will return null if there is no active map view. This is useful when writing commands designed to interact with the active map.
Drawing mode of 3D map views can be set via the SetSceneDrawingMode method. The scene drawing mode can be either perspective or isometric. Default drawing mode is perspective and new 3D map views always open in perspective mode. Scene's field of view angle can be changed using the SetFieldOfView method.
The map view also provides the context for the selected items in the Contents pane (a.k.a. "TOC"). For example, the GetSelectedLayers method returns the collection of layers that are currently selected in the Contents pane. This context is used to determine which contextual tabs to show, for example, when one or more feature layers are selected, the Feature Layer tab group will display, and the commands will act on the selected feature layers. This is useful when writing commands to work with the selected items in the Contents pane.
The map view's camera defines the area being displayed in the map. The camera can be accessed via the Camera property on the map view. You can set the map view's camera by using the ZoomTo(Camera) method. In addition to directly setting the camera, there are several overload methods for ZoomTo and PanTo that can be used to zoom to the extent of a layer, the definition of a bookmark, a specific geometry, and so on.
In some cases, you may want to provide a tool that allows the user to interactively click and sketch in the map and select or get a collection of features that intersect the sketch. The MapTool abstract class provides an easy way to author a tool that can create a sketch in the map view and return the geometry from the sketch. This geometry can then be passed into the SelectFeatures or GetFeatures method to select or return the collection of features that intersect the geometry.
The camera serves as a tool to display the world or map, and it can be moved through space to change your view. The camera describes your active point of view, in both 2D and 3D, on the map. You can get the current camera from the view using the Camera property. You can set the camera by calling the ZoomTo(Camera) method and passing in the desired camera.
The virtual camera is your window to the map. Much like a physical camera you can manipulate in the real world, the ArcGIS Pro virtual camera is moved around to view the map (in both 2D and 3D). The movement of the camera is done in coordinates of the map or the 3D axis system (X, Y, and Z).
Both 2D and 3D properties are available on the camera object. If the map view's ViewingMode is Map, you can set 2D properties. If the ViewingMode is SceneGlobal or SceneLocal, you can set 3D properties.
In 2D, the camera defines its viewing location using X and Y. The values are in the same units as those defined by the camera’s spatial reference. This will be the center point of the 2D view’s extent. The viewing direction, or rotation, of the map is defined using the camera’s Heading property. The camera’s Scale property then defines how far the view is zoomed in or out. The value is expressed as a double representing the value on the right side of the ratio. For example, a value of 1000 is equal to a scale of 1:1000.
In 3D, the camera defines its viewing location using X, Y, and Z. As with 2D, the values are stored in the same units as those defined by the camera’s spatial reference, with the additional possibility that XY units and Z units may be different. The viewing direction is defined by a combination of the Heading, Pitch, and Roll properties, which rotate, tilt, and roll how the camera looks at the content in the map.
You can use a camera to define either the coordinate you're looking from (the observer) or the position that you are looking at (the target) using the Viewpoint property. If you set the Viewpoint to LookFrom, the camera viewing location will be the coordinate of the observer. If you set the Viewpoint to LookAt, the camera viewing location will be the coordinate of the target. The camera returned from the map view's Camera property will always have a Viewpoint of LookAt.
ArcGIS.Desktop.Mapping.MapTool is an abstract base class that provides a basic implementation of ArcGIS.Desktop.Framework.Contracts.Tool
and represents a tool command used to perform interactive operations on a MapView. It provides virtual methods that can be overridden to perform actions when keyboard and mouse events occur in the map view. It also provides properties that can be set to configure the behavior of the tool, as well as methods that wrap common functions when interacting with the view. This base class will be used to create tools to interactively identify and select features in the view as well as when creating custom construction and editing tools.
Map tools are added to the <controls>
section of the add-in Config.daml. Same as buttons, map tools should be referenced within the groups that will contain them and the groups are, themselves, referenced within the individual tabs on which they should be shown. They have a corresponding code behind file which contains the map tool "class" implementation and it should also be referenced in the tool daml. For example:
<modules>
<insertModule id="..." ... caption="Module1">
<tabs>
<tab id="ProAppModule1_Tab1" caption="New Tab">
<group refID="ProAppModule1_Group1"/><!-- reference the group here -->
</tab>
</tabs>
<groups>
<group id="ProAppModule1_Group1" caption="Group 1">
<tool refID="ProAppModule1_MapTool1" size="large" /><!-- reference the tool in the group(s) -->
</group>
</groups>
<controls>
<!-- define the tool element -->
<tool id="ProAppModule1_MapTool1" caption="MapTool 1" className="MapTool1" ... />
</controls>
</insertModule>
</modules>
This is the map tool code behind:
///<summary>MapTool1 derives from the class. Note: MapTool1 is referenced in the className attribute of
///its <tool> element in the Config.daml</summary>
internal class MapTool1 : MapTool {
public MapTool1() {
...
}
...
}
The Pro SDK includes the ArcGIS Pro Map Tool template which automates much of the daml and code behind class file definition required to create a basic map tool. Simply run the Pro SDK map tool template to auto-generate the tool daml and class file definition.
Enabled/Disabled status of a map tool can be controlled by adding a condition attribute on the tool daml element. The condition can be:
- An existing Pro condition (find a complete list for each extension ArcGIS Pro DAML ID Reference)
- A custom condition (learn about making custom conditions in ProGuide Code Your Own States and Conditions)
- The daml id of a pane.
If the condition of a tool is set to be the daml id of a pane then only when instances of that type of pane are activated will your tool be enabled. The default condition for a map tool is set by the SDK Map Tool template as condition="esri_mapping_mapPane"
where esri_mapping_mapPane
is the daml id for the Pro MapView pane element.
<controls>
<!-- Enable our tool whenever a 2D or 3D map view is active. Disable it otherwise -->
<tool id="ProAppModule1_MapTool1" ... condition="esri_mapping_mapPane">
<tooltip .../>
</tool>
MapTool provides several virtual methods such as OnToolMouseDown and OnToolKeyDown that are called when the corresponding event occurs in the map view. By overriding these methods in the derived class, you can perform actions when these events occur. The mouse events provide event arguments that contain information such as which mouse button was used, as well as the ClientPoint, relative to the top left corner of the map view, where the event occurred. The client point can be passed into the ClientToMap method to return the corresponding location in the map. The keyboard events provide event argument that provides information such as which key was used.
These virtual methods are intended to perform synchronous operations. If you need to execute any asynchronous code, you should set the handled property on the event arguments to true. By doing this, the corresponding Handle...Async virtual method will be called with the same event arguments. For example, to perform an asynchronous operation when the left mouse button is pressed, you would do the following:
protected override void OnToolMouseDown(MapViewMouseButtonEventArgs e)
{
if (e.ChangedButton == System.Windows.Input.MouseButton.Left)
e.Handled = true; //Handle the event to get the call to the async method
}
protected override Task HandleMouseDownAsync(MapViewMouseButtonEventArgs e)
{
return QueuedTask.Run(() =>
{
var mapPoint = MapView.Active.ClientToMap(e.ClientPoint);
ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(string.Format("X: {0} Y: {1} Z: {2}",
mapPoint.X, mapPoint.Y, mapPoint.Z), "Map Coordinates");
});
}
By setting the IsSketchTool property to true, the tool will create a sketch in the map view with a left mouse click. The geometry type of the sketch can be set using the SketchType property, and the SketchOutputMode property can be used to specify whether the sketch geometry will be created in screen or map coordinates. If you want the tool to snap while sketching set the UseSnapping property to true. If the IsSketchTool
property is set to false (which is the default) then activating your map tool leaves the viewer in its default mode and clicks on the map will not create a sketch. If you have coded a map tool and are trying to figure out why it doesn't start sketching on the left mouse click then you may have forgotten to set the IsSketchTool
property to true.
internal class MapTool1 : MapTool {
public MapTool1() {
IsSketchTool = true;//Activate sketching when we are activated
...
The "in progress" sketch is passed to the map tool via the protected OnSketchModifiedAsync()
method. When the sketch is finished, the virtual method OnSketchCompleteAsync will be called, and it will pass in the geometry that was created by the sketch. Both of these methods can be overridden in your map tool to implement any required custom behavior.
This code snippet shows the basic outline of a map tool:
internal class MapTool1 : MapTool {
public MapTool1() {
IsSketchTool = true;//Activate sketching when we are activated
SketchType = SketchGeometryType.Rectangle;
SketchOutputMode = SketchOutputMode.Map; //use SketchOutputMode.Screen for 3D selection;
}
protected override Task OnToolActivateAsync(bool hasMapViewChanged) {
//TODO logic for when we are activated
}
protected override Task OnToolDeactivateAsync(bool hasMapViewChanged) {
//TODO logic for when we are deactivated
}
protected async override Task<bool> OnSketchModifiedAsync() {
//TODO - the sketch has been modified on the MapView
//For example, access the sketch
var sketch = this.ActiveMapView.GetCurrentSketchAsync();
//Do something...
return true;
}
protected override Task<bool> OnSketchCompleteAsync(Geometry geometry) {
//TODO - work with the sketch
}
}
When performing an interactive selection or identify using the SelectFeatures or GetFeatures method, it's important to note that only geometries in screen coordinates are supported in 3D. In 2D, both map and screen geometries are supported.
Map tools in Pro are closely coupled with Map Panes (map pane being the "container" of an individual map view). A default tool can be assigned when declaring a pane in the daml. The default tool will be automatically selected when an instance of the pane is created. When working with multiple panes, the active tool may change automatically to reflect the incoming pane. When returning to the original pane, the system will try to re-activate the most recently used tool for the pane type. Here is an excerpt from the ADMapping.daml which shows the assignment of the Pro explore tool as the map pane default.
<panes>
<pane id="esri_mapping_mapPane" caption="Map" ... defaultTool="esri_mapping_exploreTool">
...
</pane>
Animation is the process of creating a collection of sequential images and playing them back quickly to create an illusion of movement. Each image, just like a picture you take with a camera, marks a significant instance in time, and is called a keyframe. In ArcGIS Pro, animations are authored by defining a set of keyframes that the system uses to create interpolated intermediate frames. Animations can interpolate the camera position, map time, map range, and layer visibility and transparency.
Animation is a property of the Map and stores a collection of tracks which are containers for the keyframes. The tracks are returned from the Tracks property and this property always returns 4 tracks: a CameraTrack, a TimeTrack, a RangeTrack and a LayerTrack. Each track stores a corresponding keyframe type: CameraKeyframe, TimeKeyframe, RangeKeyframe, and LayerKeyframe. The track is used to get the collection of keyframes in addition to creating and deleting keyframes.
public List<CameraKeyframe> GetCameraKeyframes()
{
var mapView = MapView.Active;
if (mapView != null)
return null;
var animation = mapView.Map.Animation;
var cameraTrack = animation.Tracks.OfType<CameraTrack>().First(); //There will always be only 1 CameraTrack in the animation.
return cameraTrack.Keyframes.OfType<CameraKeyframe>().ToList();
}
A Keyframe is a visual way-point along the animation path in a map or scene. When an animation is played, values such as the location of the camera, the current map time, the current map range, and layer transparencies are interpolated between the stored states defined by the keyframe using a configurable transition type. The keyframe stores one or more values, a transition for each value and the time it exists in the track. The transition type defines how the value is interpolated from the corresponding value in the previous keyframe to its value.
For example, let's say we have 2 keyframes in a track one at a time of 0 seconds and the second at a time of 3 seconds. The first keyframe has a value for X of 1 and the second keyframe has a value for X of 5. The second keyframe defines the transition for X as Linear. What this means is at 0 seconds in the animation X is 1, at 3 seconds X is 5 and at 1.5 seconds or halfway between the value of X would be 3.
If we apply this example to the Camera which has several values including X, Y, Z which define the viewing location and Pitch, Heading and Roll which define the viewing rotation the CameraKeyframe will store all of these values in addition to a transition for each value. These values and transitions define the path the camera moves during the animation.
MapControl is a reusable control that can be embedded inside a dock pane, view pane, or a dialog and used to display project items such as 2D and 3D maps, feature layers, raster datasets, layer packages etc. The snippet below shows how you can add map control in XAML:
<mapControls:MapControl Name="mapControl" Grid.Row="1"
VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="275"
ViewContent="{Binding Path=MapContent}"
Camera="{Binding CameraProperty}">
</mapControls:MapControl>
As is shown in the snippet above, you can bind to the map control's ViewContent property to define the content currently displayed in the control and the Camera property can be used to navigate inside the map control. You can also bind to the Extent property to control the map control's extent.
The IsReady read-only property can be queried to find out whether the map control is ready to accept user input. For example, before updating the map control camera you can perform the following check:
if(MapControlWindow._mapControl.IsReady)
{
//Update the map control camera
}
You can also bind to the IsReady
property to enable or disable other controls. The snippet below shows how a button's enabled state can be bound to the map control's IsReady
property:
<Button Name="TestButton" DockPanel.Dock="Right" Style="{StaticResource buttonStyle}"
Click="OnButtonClick"
IsEnabled="{Binding Path=IsReady, ElementName=mapControl}">
</Button>
Similar to the IsReady
property is the read-only IsDrawing property that can be queried to determine whether the control is currently drawing the view content. An example usage of the IsDrawing
property would be to show a spinner for user feedback while the content is being drawn.
NOTE - You can bind another control's property to the map control's IsReady
or IsDrawing
properties as shown in the XAML snippet above but you cannot bind these properties as follows - the XAML below will give an error as IsReady
is a read-only dependency property:
<mapControls:MapControl Name="mapControl" Grid.Row="1"
VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="275"
ViewContent="{Binding Path=MapContent}"
Camera="{Binding CameraProperty}"
IsReady ="{Binding MapControlIsReady}>
</mapControls:MapControl>
Map control also raises the ControlInitialized event when it is intialized and is ready to recieve user input. Other events raised by MapControl
are ViewContentLoaded, DrawStarted, DrawComplete, CameraChanged and ExtentChanged. Specific actions can be performed by handling these events.
The map control has an OverlayControl property that can be used to display an overlay like image, text etc. inside the map control. The XAML snippet below shows an example where some text is shown in the center of the map control:
<mapControls:MapControl.OverlayControl>
<Grid>
<TextBlock TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center">
This is a simple example of using the <Bold>OverlayControl</Bold> to draw text in the map control.
</TextBlock>
</Grid>
</mapControls:MapControl.OverlayControl>
NOTE - The MapControl
is a native control and if it is placed in a transparent native window then the MapControl
will also be transparent and will not display. An example of this is if you use the MapControl
as an embeddable control by associating it with a MapTool
then the MapControl
will be hosted in a transparent native window and will not be visible.
MapControlContent represents the content that is added to a map control. The static MapControlContentFactory class is used to create the map control content. The IsItemSupported method on the MapControlContentFactory
class can be used to determine whether a particular item can be added to the map control. If an item is supported then you can use the various overloads of the MapControlContentFactory's
Create method to create the map control content.
The example below shows how to create map control content from the currently selected project item:
private MapControlContent CreateContentFromItem()
{
var curProj = Project.Current;
var selectedItem = ((curProj != null) && (curProj.SelectedItems.Count == 1)) ? curProj.SelectedItems[0] : null;
if (selectedItem == null || !MapControlContentFactory.IsItemSupported(selectedItem))
return null;
Camera camera = null;
return MapControlContentFactory.Create(new[] { selectedItem }, camera, ArcGIS.Core.CIM.MapViewingMode.Map);
}
This is an example of how you can create map control content from the currently active map in your project:
var currentMap = MapView.Active.Map;
MapControlContent _mapContent = MapControlContentFactory.Create(currentMap, MapView.Active.Extent, currentMap.DefaultViewingMode);
Samples using the Map control can be found at OverviewMapControl and MagnifierWindow
TableControl is a reusable control that can be embedded inside a pane, dock pane, or dialog and used to display content from an active map or Catalog view. You can add a TableControl
in the XAML:
<editing:TableControl AutomationProperties.AutomationId="_tableControl"
x:Name="tableControl" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
TableContent="{Binding Path=TableContent}">
</editing:TableControl>
You bind a table control's TableContent property to define the content displayed in the control.
Important properties on the TableControl include ViewMode which allows you to toggle the control in either All Records
or Selected Records
mode; ActiveFieldIndex which sets the active field of the TableControl, along with ActiveRowIndex which sets the active row.
You can also customize the row or column context menus by binding to the RowContextMenu, SelectedRowContextMenu and ColumnContextMenu properties.
The IsRowCountKnown property determines if the control knows the row count of the data source. This read-only property can be used as a check before accessing the RowCount property or selecting all rows.
The TableControlContent class defines the content source for the table control. The static TableControlContentFactory class creates the content for the table control. The IsMapMemberSupported or IsItemSupported functions determine if content can be created from the mapMember or Catalog item and displayed in the control.
The example below creates table control content from a supported map member item:
private TableControlContent CreateTableControlContent()
{
var selectedLyrs = MapView.Active.GetSelectedLayers();
var selectedSTs = MapView.Active.GetSelectedStandaloneTables();
MapMember item = null;
if (selectedLyrs != null && selectedLyrs.Count == 1)
{
item = selectedLyrs[0];
}
else if (selectedSTs != null && selectedSTs.Count == 1)
{
item = selectedSTs[0];
}
if ((item != null) && TableControlContentFactory.IsMapMemberSupported(item))
return TableControlContentFactory.Create(item);
return null;
}
This is an example of creating table control content from the selected item in the Catalog pane.
private TableControlContent CreateTableControlContentFromItem()
{
var catalogPane = Project.GetCatalogPane();
var item = catalogPane.SelectedItems.FirstOrDefault();
if ((item != null) && TableControlContentFactory.IsMapMemberSupported(item))
return TableControlContentFactory.Create(item);
return null;
}
The static TableControlCommands class provides a number of commands for use with the table control. Here is a snippet showing how to define them in xaml. Take particular notice of the CommandTarget
property. It is necessary to reference the table control's Name
property, otherwise the commands do not have the correct context and will not execute.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel LastChildFill="False" Grid.Row="0">
<Button Content="Toggle Sel" Command="editing:TableControlCommands.SwitchSelection"
CommandTarget="{Binding ElementName=tableControl}"
Style="{DynamicResource Esri_Button}"/>
<Button Content="Select All" Command="editing:TableControlCommands.SelectAll"
CommandTarget="{Binding ElementName=tableControl}"
Style="{DynamicResource Esri_Button}"/>
<Button Content="Clear Sel" Command="editing:TableControlCommands.ClearSelection"
CommandTarget="{Binding ElementName=tableControl}"
Style="{DynamicResource Esri_Button}"/>
</DockPanel>
<editing:TableControl AutomationProperties.AutomationId="_tableControl" x:Name="tableControl"
Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
TableContent="{Binding Path=TableContent}" >
</editing:TableControl>
</Grid>
The functionality exposed by the commands in TableControlCommands is also available as methods on the table control class itself. For example there are CanSwitchSelection and SwitchSelection, CanClearSelection and ClearSelection, and CanSelectAll and SelectAll methods amongst others. Use these within your ViewModel or code-behind if you need to combine them with additional functionalities.
A sample using the Table control can be found at TableControl. The ProGuide TableControl provides additional documentation and accompanies the sample.
Temporary graphics can be added to your map view or scene view using something called a "graphic overlay" associated with the map or scene views. The overlays are for showing temporary data that's not persisted when the view is closed. Overlay graphics are defined using a geometry to specify its location and a corresponding CIM symbol (technically a CIM symbol symbol reference). A CIMGraphic can also be used (which basically combines the geometry and symbol into a single entity). Graphics can be points, lines, polygon, or text (to include callouts).
In the image below, a point geometry symbolized with a star has been added to the overlay. Additionally, a second text graphic has been added, using a callout, to "add" a label to the star.
To create a Graphic overlay, use the MapView AddOverlay method. There are 3 overloads for this method that use a geometry and a Symbol reference; a CIMGraphic; or a feature oid (for the location) and Symbol Reference.
public static IDisposable AddOverlay( MapView mapView, Geometry geom, CIMSymbolReference symbol)
public static IDisposable AddOverlay(MapView mapView, CIMGraphic graphic)
public static IDisposable AddOverlay(MapView mapView, Layer layer, long oid, CIMSymbolReference symbol)
The AddOverlay method returns an IDisposable which can be used to clear the graphic. To remove the graphic, call "Dispose" on the returned IDisposable
(eg _graphic.Dispose()
). Save the IDisposable in a member variable if you need to maintain a reference to it. If you do not remove the graphic, it will automatically be removed when the mapview is closed.
The following code snippet illustrates how to create a graphic using a geometry and CIM symbol (reference).
private IDisposable _graphic = null; //defined elsewhere
// Add point graphic to the overlay at the center of the mapView
// Note: Run within QueuedTask.Run
_graphic = mapView.AddOverlay(mapView.Extent.Center, SymbolFactory.Instance.ConstructPointSymbol(ColorFactory.Instance.RedRGB, 40.0, SimpleMarkerStyle.Star).MakeSymbolReference());
// Note: Update graphic using UpdateOverlay
// mapView.UpdateOverlay(_graphic,...);
_graphic.Dispose(); //Removes the graphic
Sample: OverlayExamples
ProSnippet: Graphic Overlay
ProSnippet: Graphic Overlay with CIMPictureGraphic
ProSnippet: Add overlay graphic with text
WPF User Controls can also be added "on top of" the mapview or scene using a MapViewOverlayControl
wrapper passed as the parameter to mapView.AddOverlayControl(...)
.
To add a user control on top of Pro's mapview, first create a MapViewOverlayControl. The first parameter in the MapViewOverlayControl constructor is the WPF user control that you want to display on top of the map view. The MapViewOverlayControl constructor has parameters to configure various aspects of your user control's display and behavior such as its initial position, and whether it can be moved or resized, etc.
public MapViewOverlayControl(
FrameworkElement control,
bool canMove,
bool canResizeHorizontally,
bool canResizeVertically,
OverlayControlRelativePosition relativePosition,
double initialXRatio,
double initialYRatio
)
Our custom WPF User Control xaml (in this case two text blocks surrounded with a maroon border):
<UserControl x:Class="OverlayControlExample.ExampleControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...>
<Grid>
<Border Background="Beige" BorderBrush="Maroon" BorderThickness="4">
<StackPanel Orientation="Vertical" >
<TextBlock FontSize="20" FontWeight="Bold" Margin="50, 10"> MapView Overlay Control</TextBlock>
<TextBlock FontSize="20" FontWeight="Bold" Margin="50, 20"><Run Text="Insert controls here."/></TextBlock>
</StackPanel>
</Border>
</Grid>
</UserControl>
To add our custom user control to the mapview overlay, we create the required MapViewOverlayControl wrapper and pass an instance of or user control to the MapViewOverlayControl constructor along with the desired placement settings. We then invoke mapView.AddOverlayControl(...)
to add our user control to the mapview overlay:
var exampleControl = new ExampleControl(); //User Control
//allow it to be moved and resized
var MapViewOverlayControl = new MapViewOverlayControl(exampleControl, true, true, true, OverlayControlRelativePosition.TopLeft);
//add the wrapper to the overlay
mapView.AddOverlayControl(MapViewOverlayControl);
Refer to MapView.AddOverlayControl. This method takes a MapViewOverlayControl as its parameter.
public void AddOverlayControl(IMapViewOverlayControl overlayControl)
The MapViewOverlayControl should be held in a member variable if access is required later, or to send to RemoveOverlayControl when it is no longer needed (and should be removed from the overlay). If RemoveOverlayControl is not called, the overlay control is removed automatically when the mapview is closed.
Sample: ScribbleControl_ArcGISPro ProSnippet: MapView Overlay Control