Select to view content in your preferred language

Add a floating graphic to Map

1034
6
Jump to solution
07-28-2022 06:31 AM
BrianBulla
Honored Contributor

Hi,

Is it possible to add a graphic to the active Map that floats in space and doesn't change position when panning the map?  What I want to do is have a cross-hair type graphic centred around the centre of the map, and when the user pans around I will then use the Maps camera co-ordinate to do things with.

Hopefully that makes sense.  I've added graphics before, but they've always been tied to a specific location on the map, and hence move with the map when panning.  I kind of want the opposite effect.

0 Kudos
1 Solution

Accepted Solutions
CharlesMacleod
Esri Regular Contributor

you want a "MapViewOverlayControl". It is, essentially, a wrapper around a "standard" WPF User Control that u can add to the MapView control overlay. This overlay is used by Pro for user control content (as opposed to graphics elements content) - such as the Time slider, Edit sketch toolbar, Navigation tool "compass/navigator", and so on that sits "on top of" the map view.

To use it, create a user control - in this case it sounds like it will be something like a WPF canvas that contains your cross-hair image, centered. Wrap the user control with a MapViewOverlayControl and then add _that_ to the map view control overlay with mapView.AddOverlayerControl(....) : MapViewOverlayControl 

You should also look at the scribble control sample - it uses the map view overlay to hold a scribble control allowing users to "scribble" or "annotate" markup directly on top of the mapview (via a MapViewOverlayControl wrapping the scribble control). https://github.com/Esri/arcgis-pro-sdk-community-samples/tree/master/Map-Exploration/ScribbleControl... 

 

Your code to add the overlay control will look something like this:

var crossHairControl = new CrossHairControl(); //your user control
//do any required configuration upfront
crossHairControl.Foo = ....;
crossHairControl.Bar = ....;

//Create a MapViewOverlayControl. 
var mapViewOverlayControl = new MapViewOverlayControl(
      crossHairControl, true, true, 
      true, OverlayControlRelativePosition.Center, .5, .8);
//Add to the active map view
MapView.Active.AddOverlayControl(mapViewOverlayControl);

 

 

 

 

View solution in original post

6 Replies
CharlesMacleod
Esri Regular Contributor

you want a "MapViewOverlayControl". It is, essentially, a wrapper around a "standard" WPF User Control that u can add to the MapView control overlay. This overlay is used by Pro for user control content (as opposed to graphics elements content) - such as the Time slider, Edit sketch toolbar, Navigation tool "compass/navigator", and so on that sits "on top of" the map view.

To use it, create a user control - in this case it sounds like it will be something like a WPF canvas that contains your cross-hair image, centered. Wrap the user control with a MapViewOverlayControl and then add _that_ to the map view control overlay with mapView.AddOverlayerControl(....) : MapViewOverlayControl 

You should also look at the scribble control sample - it uses the map view overlay to hold a scribble control allowing users to "scribble" or "annotate" markup directly on top of the mapview (via a MapViewOverlayControl wrapping the scribble control). https://github.com/Esri/arcgis-pro-sdk-community-samples/tree/master/Map-Exploration/ScribbleControl... 

 

Your code to add the overlay control will look something like this:

var crossHairControl = new CrossHairControl(); //your user control
//do any required configuration upfront
crossHairControl.Foo = ....;
crossHairControl.Bar = ....;

//Create a MapViewOverlayControl. 
var mapViewOverlayControl = new MapViewOverlayControl(
      crossHairControl, true, true, 
      true, OverlayControlRelativePosition.Center, .5, .8);
//Add to the active map view
MapView.Active.AddOverlayControl(mapViewOverlayControl);

 

 

 

 

Wolf
by Esri Regular Contributor
Esri Regular Contributor

Charlie's suggestion is the way to go, however, you have to compute the x/y ratios to position the user control in the middle of the screen.  For that you have the use the active mapview's GetViewSize().  

if (MapView.Active == null) return;
var mapView = MapView.Active;
var crossHairControl = new CrossHairControl();
// use the active mapview to get the size of the mapview display
var xRatio = 0.0;
var yRatio = 0.0;
var viewSize = mapView.GetViewSize();
if (viewSize.Width != 0.0 && viewSize.Height != 0.0)
{
  var xPosition = viewSize.Width / 2;
  var yPosition = viewSize.Height / 2;
  // now offset for 1/2 of the user control's size
  xPosition -= 16;
  yPosition -= 16;
  xRatio = xPosition / viewSize.Width;
  yRatio = yPosition / viewSize.Height;
}
// Create a MapViewOverlayControl using the user control
var mapViewOverlayControl = new MapViewOverlayControl(
      crossHairControl, true, false,
      false, OverlayControlRelativePosition.Center, xRatio, yRatio);
//Add to the active map view
mapView.AddOverlayControl(mapViewOverlayControl);

I attached my sample add-in, but the result should look like this:

Wolf_0-1659197053983.png

 

BrianBulla
Honored Contributor

Thanks guys.  The sample code you both have given is a great help.  One issue I am having is adding the crosshair using a CheckBox in my WPF Dockpane.  The code seems to run, but then I get an exception saying "page can only have window or frame as parent".

BrianBulla_0-1659450911553.png

 

In my Dockpane.xaml.cs I have this (basically the same as Wolf's code), and then the exception happens after the last line runs.  The code seems to be calculating the width/height ok so it seems like I can interact with the MapView.

Any help is appreciated.

 

 

private void chkCrossHair_Checked(object sender, RoutedEventArgs e)
        {
            //draw a cross-hair in centre of active map
            
            if (MapView.Active == null) return;

            var mapView = MapView.Active;
            var crossHairControl = new CrossHairControl();

            //use the active mapview to get the size of the mapview display
            var xRatio = 0.0;
            var yRatio = 0.0;
            var viewSize = mapView.GetViewSize();

            if (viewSize.Width != 0.0 && viewSize.Height != 0.0)
            {
                var xPosition = viewSize.Width / 2;
                var yPosition = viewSize.Height / 2;
                // now offset for 1/2 of the user control's size
                xPosition -= 16;
                yPosition -= 16;
                xRatio = xPosition / viewSize.Width;
                yRatio = yPosition / viewSize.Height;
            }

            // Create a MapViewOverlayControl using the user control
            var mapViewOverlayControl = new MapViewOverlayControl(
                  crossHairControl, true, false,
                  false, OverlayControlRelativePosition.Center, xRatio, yRatio);
            //Add to the active map view
            mapView.AddOverlayControl(mapViewOverlayControl);

        }

 

 

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Like Charles said we don't have enough code to see the problem, but i would also check your CrossHairControl and make sure that mapViewOverlayControl is defined.  

CharlesMacleod
Esri Regular Contributor

you have a threading issue. Usually an InvalidOperation exception is thrown when u create something on the _background_ thread that needs to be created on the UI thread (the reverse of most cases w the Pro SDK which do require u to use the QTR).

However it's not possible to tell from just this snippet. Make sure that the complete sequence occurs on the UI thread in this case.

BrianBulla
Honored Contributor

Thanks guys.  So the problem was with my CrossHairControl.  Once I deleted it and created a new one, all is good.  No issues with the threading.  Thanks for all your help with this!!