Displaying web map pop-up windows
Pop-up windows can be defined on a web map to show information about something in the map, such as hiking trails, land values, or unemployment rates. The definition of the pop-up window, which tells what fields to display, is saved in the web map. When a web map is read into an application with the ArcGIS Runtime SDK for WPF's WebMap.Document class, the pop-up window information is included and can be displayed. The following are the different types of data that can have pop-up windows associated with them:
- Editable layers you create on a map (termed map notes)—These are authored by adding features directly to a web map. When the features are added, a pop-up window can be created to show information about the feature.
- Feature layers hosted in ArcGIS feature services—These services are added to the web map and pop-ups can be configured on the layer. See Configuring pop-up windows.
- Layers hosted in ArcGIS map services—These services contain one or more layers. Each of those layers can have pop-ups configured the same way they can be configured for a feature layer.
Map notes and feature layers each support a single pop-up definition, and their pop-ups are accessed through either MapTips or the WebMap.Document.PopupTemplateProperty. Map services, on the other hand, are composed of one or more layers, each of which can have a pop-up definition. These are accessed through the WebMap.Document.PopupTemplatesProperty. Both the PopupTemplateProperty and the PopupTemplatesProperty ultimately provide access to a data template to use to display the pop-up. Windows Presentation Foundation (WPF) data templates specify how to show information and can be associated with any content control, such as a ContentPresenter or an InfoWindow.
This topic includes the following sections:
- Showing pop-ups as MapTips
- Using the PopupTemplateProperty to get and display a DataTemplate
- Using the PopupTemplatesProperty to get and display a dictionary of DataTemplates
The code sections in this topic assume that you have already read a web map into your application using WebMap.Document.GetMapAsync. See Adding a web map.
The web map with the ID db600ea7e08347ed864617e14854af14 contains both feature and map services with pop-ups and can be used with the event handlers shown in this topic.
Showing pop-ups as MapTips
MapTips are automatically used to display the pop-up windows on any map notes or feature layer. No code is required to achieve this functionality.
However, you might need to customize the MapTip so that it matches your application's look and feel. You can do so by customizing the MapTip as a Border as part of the GetMapCompleted event, called when the map has been retrieved. See the following code:
void webMap_GetMapCompleted(object sender, GetMapCompletedEventArgs e)
{
if (e.Error == null)
{
MyMap.Extent = e.Map.Extent;
LayerCollection layerCollection = new LayerCollection();
foreach (Layer layer in e.Map.Layers)
{
// Map notes are stored in graphics layers.
// Feature layers are a type of graphics layer.
if (layer is GraphicsLayer)
{
GraphicsLayer glayer = layer as GraphicsLayer;
Border border = glayer.MapTip as Border;
if (border != null)
{
border.Background = new SolidColorBrush(Color.FromArgb(200, 102, 150, 255));
border.CornerRadius = new CornerRadius(4);
}
}
layerCollection.Add(layer);
}
e.Map.Layers.Clear();
MyMap.Layers = layerCollection;
}
}
Using the PopupTemplateProperty
You can also display the information contained in pop-up windows associated with both map notes and feature layers by retrieving and displaying the layer's pop-up template. The WebMap.Document.PopupTemplateProperty is a dependency property and contains a data template for the pop-up window that can be displayed in any content presenter. In the following example, an InfoWindow is used to display the pop-up window's information.
The following code assumes there is an InfoWindow named MyInfoWindow defined in the application, as well as a map named MyMap. The code belongs in the MouseClick event on the map, defined as follows:
private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
{
// Code from the following steps is placed here to show the pop-up window.
}
- Close the InfoWindow in case one is already displayed.
MyInfoWindow.IsOpen = false;
- Loop through the layers in the map, finding a graphics layer. Since map notes are stored in a graphics layer, and feature layers are a type of graphics layer, both map notes with pop-ups and feature layers with pop-ups can be displayed following this workflow.
MyInfoWindow.IsOpen = false; foreach (Layer layer in MyMap.Layers) { if (layer is GraphicsLayer) { } }
- From that layer, retrieve the PopupTemplateProperty, which is DataTemplate for the layer. Since the PopupTemplateProperty is a dependency property, the value can be retrieved using GetValue. If the layer has a data template, stop processing the layers and the next step shows how the pop-up information is displayed. If the layer has no DataTemplate, the PopupTemplateProperty will be null, and the next graphics layer found.
MyInfoWindow.IsOpen = false; foreach (Layer layer in MyMap.Layers) { if (layer is GraphicsLayer) { GraphicsLayer glayer = layer as GraphicsLayer; DataTemplate dt = layer.GetValue(Document.PopupTemplateProperty) as DataTemplate; if (dt != null) { break; } } }
- When a layer with a DataTemplate is found, find any graphics in that layer at the location clicked.
MyInfoWindow.IsOpen = false; foreach (Layer layer in MyMap.Layers) { if (layer is GraphicsLayer) { GraphicsLayer glayer = layer as GraphicsLayer; DataTemplate dt = layer.GetValue(Document.PopupTemplateProperty) as DataTemplate; if (dt != null) { System.Windows.Point screenPnt = MyMap.MapToScreen(e.MapPoint); // Account for difference between map and application origin. GeneralTransform generalTransform = MyMap.TransformToVisual( Application.Current.MainWindow ); System.Windows.Point transformScreenPnt = generalTransform.Transform(screenPnt); IEnumerable<Graphic> selected = glayer.FindGraphicsInHostCoordinates(transformScreenPnt); break; } } }
- Use the first of the returned features to set up an InfoWindow to display the pop-up window. Set the InfoWindow's anchor to the location on the map that was clicked. Set the InfoWindow's content template to the DataTemplate found on the layer, and set the content of the InfoWindow to the attributes of the first feature. Show the InfoWindow, which contains the pop-up information. In the following code, only the first graphic's InfoWindow is shown:
MyInfoWindow.IsOpen = false; foreach (Layer layer in MyMap.Layers) { if (layer is GraphicsLayer) { GraphicsLayer glayer = layer as GraphicsLayer; DataTemplate dt = layer.GetValue(Document.PopupTemplateProperty) as DataTemplate; if (dt != null) { System.Windows.Point screenPnt = MyMap.MapToScreen(e.MapPoint); // Account for difference between map and application origin. GeneralTransform generalTransform = MyMap.TransformToVisual(Application.Current.MainWindow); System.Windows.Point transformScreenPnt = generalTransform.Transform(screenPnt); IEnumerable<Graphic> selected = glayer.FindGraphicsInHostCoordinates(transformScreenPnt); foreach (Graphic g in selected) { MyInfoWindow.Anchor = e.MapPoint; MyInfoWindow.ContentTemplate = dt; MyInfoWindow.Content = g.Attributes; MyInfoWindow.IsOpen = true; break; // Only show the InfoWindow for the first feature found. } } } }
Caution:MyInfoWindow, used in the previous code section, already had the Map property of the InfoWindow set to the map returned from reading the web map. Without the Map property set, the InfoWindow will not display.
Tip:If you do not clear the MapTip property on the layer, both the InfoWindow and the MapTip show the pop-up information. You should clear the MapTip property when the web map is read, in the Document.WebMap.GetMapCompleted event.
Using the PopupTemplatesProperty
A web map containing an ArcGIS map service can have pop-ups configured on the individual layers within the map service. The WebMap.Document.PopupTemplatesProperty is a dependency property and contains a dictionary that maps each layer's ID to a DataTemplate for its pop-up window, if a pop-up window was defined on that layer. The dictionary of DataTemplates for the layers can be retrieved, then the individual DataTemplates can be displayed in any content presenter. Since a map service is an image on the client, a query must be done to retrieve information about the features that will have their information displayed in pop-ups.
The following steps build an event so that when clicked, the map displays the pop-up window of a feature at that location.
The following code assumes there is an InfoWindow named MyInfoWindow defined in the application, as well as a map named MyMap. The code belongs in the MouseClick event on the map, defined as follows:
private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
{
// Code from the following steps is placed here to show the pop-up window.
}
- Close the InfoWindow in case one is already displayed, and define some variables to reference the map service layer that you are working with, its DataTemplate, and its layer ID.
MyInfoWindow.IsOpen = false; double mapScale = (MyMap.Resolution * 39.3700787) * 96; ArcGISDynamicMapServiceLayer popupLayer = null; DataTemplate dt = null; int layid = 0;
- Loop through the layers in the map, finding the first layer with the PopupTemplatesProperty set.
MyInfoWindow.IsOpen = false; double mapScale = (MyMap.Resolution * 39.3700787) * 96; ArcGISDynamicMapServiceLayer popupLayer = null; DataTemplate dt = null; int layid = 0; foreach (Layer layer in MyMap.Layers) { if (layer.GetValue(Document.PopupTemplatesProperty) != null) { } }
- To later query for the features at the location, store a reference to the service layer that uses the PopupTemplatesProperty field.
MyInfoWindow.IsOpen = false; double mapScale = (MyMap.Resolution * 39.3700787) * 96; ArcGISDynamicMapServiceLayer popupLayer = null; DataTemplate dt = null; int layid = 0; foreach (Layer layer in MyMap.Layers) { if (layer.GetValue(Document.PopupTemplatesProperty) != null) { popupLayer = layer as ArcGISDynamicMapServiceLayer; } }
- From that layer, retrieve the PopupTemplatesProperty, which is an IDictionary of the layer IDs and their pop-up DataTemplates. Since the PopupTemplatesProperty is a dependency property, the value can be retrieved using GetValue. This provides access to the DataTemplates that were found, along with the corresponding layer ID. For this example, only a single layer's ID and DataTemplate are stored so that it can be displayed in the following steps.
MyInfoWindow.IsOpen = false; double mapScale = (MyMap.Resolution * 39.3700787) * 96; ArcGISDynamicMapServiceLayer popupLayer = null; DataTemplate dt = null; int layid = 0; foreach (Layer layer in MyMap.Layers) { if (layer.GetValue(Document.PopupTemplatesProperty) != null) { popupLayer = layer as ArcGISDynamicMapServiceLayer; IDictionary<int, DataTemplate> idict = layer.GetValue(Document.PopupTemplatesProperty) as IDictionary<int, DataTemplate>; foreach (LayerInfo linfo in popupLayer.Layers) { if (((mapScale > linfo.MaxScale // in scale range && mapScale < linfo.MinScale) || (linfo.MaxScale == 0.0 // no scale dependency && linfo.MinScale == 0.0) || (mapScale > linfo.MaxScale // minscale = 0.0 = infinity && linfo.MinScale == 0.0)) && idict.ContainsKey(linfo.ID)) // id present in dictionary { layid = linfo.ID; dt = idict[linfo.ID]; break; } } } }
- If there is a DataTemplate, perform a query on the layer with the DataTemplate to get features at the location that was clicked. To query, first determine the type of layer so that the uniform resource locator (URL) can be retrieved. In this example, pop-ups on ArcGIS dynamic and tiled map service layers are displayed.
MyInfoWindow.IsOpen = false; double mapScale = (MyMap.Resolution * 39.3700787) * 96; ArcGISDynamicMapServiceLayer popupLayer = null; DataTemplate dt = null; int layid = 0; foreach (Layer layer in MyMap.Layers) { if (layer.GetValue(Document.PopupTemplatesProperty) != null) { popupLayer = layer as ArcGISDynamicMapServiceLayer; IDictionary<int, DataTemplate> idict = layer.GetValue(Document.PopupTemplatesProperty) as IDictionary<int, DataTemplate>; foreach (LayerInfo linfo in popupLayer.Layers) { if (((mapScale > linfo.MaxScale // in scale range && mapScale < linfo.MinScale) || (linfo.MaxScale == 0.0 // no scale dependency && linfo.MinScale == 0.0) || (mapScale > linfo.MaxScale // minscale = 0.0 = infinity && linfo.MinScale == 0.0)) && idict.ContainsKey(linfo.ID)) // id present in dictionary { layid = linfo.ID; dt = idict[linfo.ID]; break; } } if (dt != null) { QueryTask qt = new QueryTask(string.Format("{0}/{1}", popupLayer.Url, layid)); ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query(); query.Geometry = e.MapPoint; query.OutSpatialReference = MyMap.SpatialReference; query.OutFields.Add("*"); qt.ExecuteAsync(query); } } }
- Add an event handler so that the first of the returned features is used to set up an InfoWindow to display the pop-up window. Set the InfoWindow's anchor to the location on the map that was clicked. Set the InfoWindows's content template to the DataTemplate found on the layer, and set the content of the InfoWindow to the attributes of the first feature. Show the InfoWindow, which contains the pop-up information.
MyInfoWindow.IsOpen = false; double mapScale = (MyMap.Resolution * 39.3700787) * 96; ArcGISDynamicMapServiceLayer popupLayer = null; DataTemplate dt = null; int layid = 0; foreach (Layer layer in MyMap.Layers) { if (layer.GetValue(Document.PopupTemplatesProperty) != null) { popupLayer = layer as ArcGISDynamicMapServiceLayer; IDictionary<int, DataTemplate> idict = layer.GetValue(Document.PopupTemplatesProperty) as IDictionary<int, DataTemplate>; foreach (LayerInfo linfo in popupLayer.Layers) { if (((mapScale > linfo.MaxScale // in scale range && mapScale < linfo.MinScale) || (linfo.MaxScale == 0.0 // no scale dependency && linfo.MinScale == 0.0) || (mapScale > linfo.MaxScale // minscale = 0.0 = infinity && linfo.MinScale == 0.0)) && idict.ContainsKey(linfo.ID)) // id present in dictionary { layid = linfo.ID; dt = idict[linfo.ID]; break; } } if (dt != null) { QueryTask qt = new QueryTask(string.Format("{0}/{1}", popupLayer.Url, layid)); qt.ExecuteCompleted += (s, qe) => { if (qe.FeatureSet.Features.Count > 0) { Graphic g = qe.FeatureSet.Features[0]; MyInfoWindow.Anchor = e.MapPoint; MyInfoWindow.ContentTemplate = dt; MyInfoWindow.Content = g.Attributes; MyInfoWindow.IsOpen = true; } }; ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query(); query.Geometry = e.MapPoint; query.OutSpatialReference = MyMap.SpatialReference; query.OutFields.Add("*"); qt.ExecuteAsync(query); } } }
Caution:MyInfoWindow, used in the previous code section, already had the Map property of the InfoWindow set to the map returned from reading the web map. Without the Map property set, the InfoWindow will not display.