Skip To Content

Display map overlays

In this topic

The MapView control has an Overlays collection that can be populated with a reasonable number of UI elements to display on top of the map. These elements are commonly used to display custom labels for locations you want to emphasize on the map, to display attribute information for a feature clicked by the user, and so on. You can update overlay element position and visibility to display them when and where they are appropriate for your app. Since an overlay can contain a combination of FrameworkElement objects, you can build sophisticated UI elements that contain text, images, controls, and more.

Caution:

Map overlays are designed to display a limited number of elements on the map. Displaying too many items in the map overlays collection will produce poor display performance for your app.

When to use overlays

ArcGIS Runtime SDK for .NET provides several options for rendering things on a map. Each display option is designed to accommodate specific use cases that your app may require, and to ensure optimal performance for your app. You should know the advantages and drawbacks for each display option so you can use the proper tool for each scenario. The following descriptions provide an overview of the options available for displaying dynamic content in the map view.

  • Map overlays—Used to display UI elements anchored to a location on the map (often called MapTips). They are built from FrameworkElement objects and require more resources to render than features or graphics. Map overlays give you the ability to design rich UI elements combining text, images, and various controls and are designed to display a small number of elements over the map (less than 20 or so). Map overlay elements always display on top of any other objects displayed in the map view.
  • Graphics overlays—Allow you to associate a collection of Graphic elements with the MapView. Graphics have geometry and attributes that are stored in memory; consequently, they must be built programmatically and aren't persisted. A GraphicsOverlay always displays on top of all layers in the map but below any map overlay elements. It displays over any Map you put in the map view and will automatically adjust if the spatial reference changes. While a graphics overlay can display more elements than a map overlay, because they are stored in memory, graphics overlays are designed to display a moderate number of features that belong more with your app rather than with a particular map. A GraphicsOverlay is best suited for displaying map information that is specific to the current user session or things that need to be displayed temporarily. Showing query results or buffer polygons on the map are examples suited to using a GraphicsOverlay.
    Note:

    Because they are not in the map, graphics in overlays will not appear in a map's legend or be displayed when the map is printed.

  • Graphic layers—Also contain a collection of Graphic elements but differ from a GraphicsOverlay because the graphics are used to represent data in the Map rather than temporary elements in the MapView. A GraphicsLayer is added to a map's layer collection, and the position of graphics within the map display depends on the position of the layer within the collection. If added as the last layer in the collection, a GraphicsLayer will display on top of all other layers in the map but below any graphics overlays or map overlay elements. Tracking a fleet of vehicles or showing stops along a route are examples suited to using a GraphicsLayer.
  • Feature layers—Display a collection of Feature objects. A Feature is similar to a Graphic in that they both have geometry and attributes that describe a location (as a point, line, or polygon). Unlike graphics, which are stored in memory, features are stored physically in a table and are persisted between sessions. For this reason, features are better suited for displaying a common set of data to all users of your app and between user sessions. Using features instead of graphics can dramatically reduce memory usage and are ideal for working with large datasets and on devices that have limited memory available. A FeatureLayer provides the best available performance and is designed to display several thousands of features quickly and efficiently.
    Note:

    For a more detailed comparison of features and graphics, see the Features and graphics topic.

Define a basic map overlay

The map overlay collection is managed by the OverlayItemsControl, which contains standard .NET UI elements. Any type of FrameworkElement can be used as an overlay element in the control. A basic map overlay can consist of a single element, such as a TextBlock or Image, or you can build more complex overlay elements using container controls, such as Grid, Canvas, Border, and so on, to contain a group of controls.

Elements can be added to the map overlay collection at design time using XAML or at run time using code. The map location of an overlay cannot be defined in XAML, it can only be set in your code. The following example uses XAML to add a TextBlock to the overlay collection of the MapView. At run time, you can use code to set the overlay anchor point to display the text at the desired location.

Note:

In each of the code examples in this topic, the following xml namespace references are assumed:

xmlns:esri="using:Esri.ArcGISRuntime.Controls"
xmlns:lyr="using:Esri.ArcGISRuntime.Layers"

<esri:MapView x:Name="mapView">
    <esri:Map>
        <lyr:ArcGISTiledMapServiceLayer
            ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer" />
    </esri:Map>

     <esri:MapView.Overlays>
        <esri:OverlayItemsControl>
            <TextBlock x:Name="utahMapTip" 
                       Text="Somewhere in Utah" 
                       FontWeight="Bold" Foreground="White" 
                       Visibility="Collapsed"/>
        </esri:OverlayItemsControl>        
     </esri:MapView.Overlays>
</esri:MapView>

Use code to position your map overlay when the app is running. You may want to show an overlay when the user clicks a location on the map or in response to some other UI interaction. You may want to show an overlay when the application initializes, as shown in the following example:

public MainPage()
{
    this.InitializeComponent();

    // handle the Loaded event for the MapView to position the map overlay
    this.MyMapView.Loaded += SetMapTip; 
}

void SetMapTip(object sender, RoutedEventArgs e)
{
    // get the overlay element (should only be one in the collection)
    var utahMapTip = this.MyMapView.Overlays.Items[0] as FrameworkElement;
    if (utahMapTip == null) { return; }

    // create a map point for the overlay position
    var utahPoint = new Esri.ArcGISRuntime.Geometry.MapPoint(-112.19568, 39.056601, Esri.ArcGISRuntime.Geometry.SpatialReferences.Wgs84);

    // call a static method on MapView to set the attached OverlayAnchor property
    Esri.ArcGISRuntime.Controls.MapView.SetViewOverlayAnchor(utahMapTip, utahPoint);

    // make the overlay element visible
    utahMapTip.Visibility = Visibility.Visible;
}

Map overlay to display text

The following example creates and positions the same overlay using code:

var tb = new TextBlock();
tb.Foreground = new SolidColorBrush(Colors.White);
tb.FontWeight = FontWeights.Bold;
tb.Text = "Somewhere in Utah";

var geoPoint = new Esri.ArcGISRuntime.Geometry.MapPoint(-112.19568, 39.05660, Esri.ArcGISRuntime.Geometry.SpatialReferences.Wgs84);

this.MyMapView.Overlays.Items.Add(tb);
Esri.ArcGISRuntime.Controls.MapView.SetViewOverlayAnchor(tb, geoPoint);

In the previous example, the location of the overlay element is set by calling a static method on the MapView class. This is because the ViewOverlayAnchor property is an attached property defined in the map view. To get the current location of an overlay element, call MapView.GetViewOverlayAnchor, and pass in a reference to the overlay element. To set a new position, call MapView.SetViewOverlayAnchor, and pass in the element and a map point for the new location. This is the technique you'll use when moving an overlay according to user interaction, such as a tap or mouse click on the map.

Define a map overlay composed of several elements

If you need to display more than a single piece of information in a map overlay element, such as text and an image, for example, you can create your overlay with a container control. Container controls are elements such as Grid, Canvas, and Border. They allow you to group several controls as a single map overlay element.

The following example creates a Grid element to display two text blocks and an image:

<esri:MapView x:Name="mapView">
    <esri:Map>
        <lyr:ArcGISTiledMapServiceLayer
            ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer" />
    </esri:Map>

    <esri:MapView.Overlays>
        <esri:OverlayItemsControl>
            <Grid x:Name="ferneyOverlay" 
                  HorizontalAlignment="Right" VerticalAlignment="Top" 
                  MaxWidth="200"
                  Visibility="Collapsed">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="20" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <Border Background="#CC000000" BorderThickness="1,1,1,0" Margin="0,0,0,-1" BorderBrush="White" Grid.ColumnSpan="2">
                    <StackPanel Margin="10">
                        <TextBlock Text="Ferney-Voltaire" FontWeight="Bold" Foreground="White" />
                        <Image Width="200">
                            <Image.Source>
                                <BitmapImage DecodePixelWidth="200"  
        UriSource="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Voltaire_statue%2C_Ferney.JPG/220px-Voltaire_statue%2C_Ferney.JPG" />
                            </Image.Source>
                        </Image>
                        <TextBlock TextWrapping="Wrap" Foreground="White"
                    Text="Les opinions ont plus causé de maux sur ce petit globe que la peste et les tremblements de terre. -Voltaire"/>
                    </StackPanel>
                </Border>

                <Path StrokeThickness="1" Fill="#CC000000" Stroke="White" Stretch="Fill" HorizontalAlignment="Left" Data="M0,0 L0,1 1,0" Grid.Row="1" />
                <Path StrokeThickness="1" Fill="#CC000000" Stroke="White" Stretch="Fill" VerticalAlignment="Top" Data="M0,0 L1,0" Grid.Row="1" Grid.Column="1" />
            </Grid>
        </esri:OverlayItemsControl>        
    </esri:MapView.Overlays>
</esri:MapView>

The location of the overlay can be defined at run time. The following example shows how to find specific map overlay elements by name and set their position:

MapPoint overlayLocation = null;

// find each overlay element from the MapView using its name
var ferneyTip = this.MyMapView.FindName("ferneyOverlay") as FrameworkElement;
var utahTip = this.MyMapView.FindName("utahMapTip") as FrameworkElement;

// if the overlay element is found, set its position and make it visible
if (ferneyTip != null)
{
    overlayLocation = new Esri.ArcGISRuntime.Geometry.MapPoint(6.1081, 46.2558, Esri.ArcGISRuntime.Geometry.SpatialReferences.Wgs84);
    Esri.ArcGISRuntime.Controls.MapView.SetViewOverlayAnchor(ferneyTip, overlayLocation);
    ferneyTip.Visibility = Visibility.Visible; 
}

if (utahTip != null)
{
    overlayLocation = new Esri.ArcGISRuntime.Geometry.MapPoint(-112.19568, 39.05660, Esri.ArcGISRuntime.Geometry.SpatialReferences.Wgs84);
    Esri.ArcGISRuntime.Controls.MapView.SetViewOverlayAnchor(utahTip, overlayLocation);
    utahTip.Visibility = Visibility.Visible; 
}

Caution:

You may be tempted to get a reference to your overlay element in your code behind using syntax such as var overlay = this.MyOverlayElement. Although this will work at design time, and you will not get build errors when running, the reference (for example, overlay variable) will be null when your app runs. This is because objects inside the MapView control are not in the page's control hierarchy and, therefore, cannot be referenced from the page. Instead, you must use the FindName method on your map view to get a reference to a specific overlay element as shown in the previous example.

Map overlay element showing both text and an image

Using a container element as your map overlay gives you more options for formatting backgrounds and borders. In the previous example, a dark background color makes the text more readable. Border and Path elements are used to create a callout effect and to help pinpoint the map location associated with the overlay element.

Update an overlay at run time

You may need to move a map overlay element or update its contents while your app is running. Your overlay may be acting as an identify dialog, for example, displaying information for features as they are clicked on the map. Since they are familiar XAML FrameworkElement objects, overlay elements can also be shown or hidden as appropriate by setting their Visibility property.

Update overlay content

If your overlay will show the same information, but for different Feature objects as the app runs, you can use data binding to specify which attributes to display. When the user selects a new Feature in the map, you can change the data binding to show updated attribute information.

The following example shows XAML that creates a map overlay with data binding to display attribute information. The data context in this example will be a Graphic object (a type of Feature) and will be set when the app runs.

<Border x:Name="countyMapTip" Background="#CC000000" BorderThickness="1" BorderBrush="White">
    <StackPanel Margin="10">
        <TextBlock Text="{Binding Attributes[name]}" 
                FontWeight="Bold" FontSize="26" Foreground="White" />
        <TextBlock Text="{Binding Attributes[state_name]}"  
                FontSize="16" Foreground="LightGoldenrodYellow" />
    </StackPanel>
</Border>

If the data context was from point features, you could also bind the overlay anchor position to the Geometry property using XAML as shown in the following example. The ViewBase.ViewOverlayAnchor property requires a point, so this binding will not work for polygon or polyline features.

<Border x:Name="countyMapTip" Background="#CC000000" BorderThickness="1" BorderBrush="White" 
    esri:ViewBase.ViewOverlayAnchor="{Binding Geometry}">
    <StackPanel Margin="10">
        <TextBlock Text="{Binding Attributes[name]}" 
                FontWeight="Bold" FontSize="26" Foreground="White" />
        <TextBlock Text="{Binding Attributes[state_name]}"  
                FontSize="16" Foreground="LightGoldenrodYellow" />
    </StackPanel>
</Border>

To update the information in the overlay, you need to set the data context for the countyMapTip element with a Graphic object. To show the information, the Graphic must have name and state_name attributes.

Tip:

If a property is not available in an object used in your binding, the data will not appear for the bound properties, but an exception will not be thrown by the app. To track down data binding issues, check the Visual Studio Output window as the app is running your data binding code. Messages regarding data binding issues will be shown here.

The following example queries a map service layer of United States counties with a point clicked by the user. If the query returns a result, the graphic is bound to the map overlay element (countyMapTip). The data binding defined for this element in the previous example displays name and state_name attributes for the graphic.

private async void mapView_Tapped(object sender, TappedRoutedEventArgs e)
{
    // get the map overlay element by name
    var mapOverlay = this.MyMapView.FindName("countyMapTip") as FrameworkElement;

    // get the location tapped on the map
    var screenPoint = e.GetPosition(this.MyMapView);
    var mapPoint = this.MyMapView.ScreenToLocation(screenPoint);

    // create a task to query the US counties layer with the map point
    var uri = new Uri("http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/3");
    var queryTask = new Esri.ArcGISRuntime.Tasks.Query.QueryTask(uri);

    var query = new Esri.ArcGISRuntime.Tasks.Query.Query(mapPoint);
    query.OutFields.Add("name");
    query.OutFields.Add("state_name");
    query.ReturnGeometry = false;

    // execute the query and check for a result
    var result = await queryTask.ExecuteAsync(query);
    if (result.FeatureSet.Features.Count > 0)
    {
        // get the first feature in the results 
        var feature = result.FeatureSet.Features[0];
        // verify that the overlay was found
        if (mapOverlay != null)
        {
            // set its data context with the feature
            mapOverlay.DataContext = feature;
        }
    }
}

Stationary MapTip overlay updated with data bound attributes

The previous example works well to update the information displayed in the overlay but does not update the overlay position on the map (anchor point).

Move a map overlay element

A map overlay element can be moved by assigning a new anchor point, which is defined as an attached property on the MapView class. The anchor point is defined in map units. The following syntax is used to get or set the anchor location for an overlay element:

// get the current anchor location
//   -find the overlay element by name
var myOverlayElement = this.MyMapView.FindName("mapTipOverlay") as FrameworkElement;

//   -pass in the UI Element (must be in the current MapView's overlay collection)
//   -get back a MapPoint object
var mapPoint = MapView.GetViewOverlayAnchor(myOverlayElement);

// set a new anchor location
//   -pass in the UI Element (must be in the current MapView's overlay collection)
//   -pass in a MapPoint that defines the new location
MapView.SetViewOverlayAnchor(myOverlayElement, updatedMapPoint);

To use the attached properties described in the previous example, you need to pass in a reference to the FrameworkElement that serves as your map overlay. Use the FindName method on the MapView (defined on the FrameworkElement base class) to get the overlay element using the name you assigned in XAML.

The following example builds on code in a previous example to move the MapTip element (countyMapTip) to the location clicked by the user. The overlay element will also be shown or hidden depending on whether or not a feature was found by the click.

private async void mapView_Tapped(object sender, TappedRoutedEventArgs e)
{
    // get the map overlay element by name
    var mapOverlay = this.MyMapView.FindName("countyMapTip") as FrameworkElement;

    // get the location tapped on the map
    var screenPoint = e.GetPosition(this.MyMapView);
    var mapPoint = this.MyMapView.ScreenToLocation(screenPoint);

    // create a task to query the US counties layer with the map point
    var uri = new Uri("http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/3");
    var queryTask = new Esri.ArcGISRuntime.Tasks.Query.QueryTask(uri);

    var query = new Esri.ArcGISRuntime.Tasks.Query.Query(mapPoint);
    query.OutFields.Add("name");
    query.OutFields.Add("state_name");
    query.ReturnGeometry = false;

    // execute the query and check for a result
    var result = await queryTask.ExecuteAsync(query);
    if (result.FeatureSet.Features.Count > 0)
    {
        // get the first feature in the results 
        var feature = result.FeatureSet.Features[0];
        // verify that the overlay was found
        if (mapOverlay != null)
        {
            // set its data context with the feature
            mapOverlay.DataContext = feature;
            // move it to the point clicked by the user
            Esri.ArcGISRuntime.Controls.MapView.SetViewOverlayAnchor(mapOverlay, mapPoint);
            // show it
            mapOverlay.Visibility = Windows.UI.Xaml.Visibility.Visible;
        }
    }
}

Map overlay shown at the location clicked by the user

For samples that illustrate the use of map overlays, including the display of MapTips for a feature layer, see the ArcGIS Runtime SDK for .NET samples repository.

Related topics