Identify features in a WMS layer and display the associated popup content.
Use case
Map symbols generally showcase only one or two data points via color or size, but the data can contain many more attributes than what is shown on the map. These additional attributes can be shown in an attribute table or popup for the map viewer to explore interactively. For example, the map might be symbolized to show population density with different shades of a color, but it might contain other interesting attributes to explore in a table, such as median income, educational attainment, and median age.
How to use the sample
Tap a feature to identify it. The HTML content associated with the feature will be displayed in a web view.
How it works
- A WMS layer is added via URL and a layer name.
- When the map is tapped,
MapView.IdentifyLayerAsync
is used to find matching results within the WMS layer. - If there is a matching feature, the HTML property is taken via a lookup in the feature's attribute dictionary.
- This particular server will produce an identify result with an empty table when there is no identified feature. In all other cases, a table with an OBJECTID column is added. This sample checks for the presence of OBJECTID in the HTML, and doesn't display the result if it is missing.
- The HTML is displayed in the web view.
Note: the service returns HTML regardless of whether there was an identify result. The sample uses a simple rule to hide empty results.
Relevant API
- IdentifyLayerResult
- IdentifyLayerResult.GeoElements
- MapView.IdentifyLayerAsync
- WmsFeature
- WmsFeature.Attributes
- WmsLayer
About the data
This sample shows a map of surface water sources in each U.S. state. States with more surface and ground water sources appear darker blue. The attribute table includes counts of surface and ground water sources. This map service is provided by the U.S. EPA.
Tags
callout, identify, OGC, web map service, WMS
Sample Code
// Copyright 2022 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
// language governing permissions and limitations under the License.
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Ogc;
using Esri.ArcGISRuntime.UI;
namespace ArcGIS.Samples.WmsIdentify
{
[ArcGIS.Samples.Shared.Attributes.Sample(
name: "Identify WMS features",
category: "Layers",
description: "Identify features in a WMS layer and display the associated popup content.",
instructions: "Tap a feature to identify it. The HTML content associated with the feature will be displayed in a web view.",
tags: new[] { "OGC", "WMS", "callout", "identify", "web map service" })]
public partial class WmsIdentify : ContentPage
{
// Create and hold the URL to the WMS service showing EPA water info
private Uri _wmsUrl = new Uri("https://sampleserver6.arcgisonline.com/arcgis/services/SampleWorldCities/MapServer/WMSServer?request=GetCapabilities&service=WMS");
// Create and hold a list of uniquely-identifying WMS layer names to display
private List<String> _wmsLayerNames = new List<string> { "1" };
// Hold the WMS layer
private WmsLayer _wmsLayer;
public WmsIdentify()
{
InitializeComponent();
// Create the UI, setup the control references and execute initialization
_ = Initialize();
}
private async Task Initialize()
{
// Create new Map with basemap
Map myMap = new Map(BasemapStyle.ArcGISImageryStandard);
// Provide used Map to the MapView
MyMapView.Map = myMap;
// Disabling the WrapAroundMode property for the Mapview
MyMapView.WrapAroundMode = WrapAroundMode.Disabled;
// Create a new WMS layer displaying the specified layers from the service
_wmsLayer = new WmsLayer(_wmsUrl, _wmsLayerNames);
try
{
// Load the layer
await _wmsLayer.LoadAsync();
// Add the layer to the map
MyMapView.Map.OperationalLayers.Add(_wmsLayer);
// Zoom to the layer's extent
MyMapView.SetViewpoint(new Viewpoint(_wmsLayer.FullExtent));
// Subscribe to tap events - starting point for feature identification
MyMapView.GeoViewTapped += MyMapView_GeoViewTapped;
}
catch (Exception e)
{
await Application.Current.MainPage.DisplayAlert("Error", e.ToString(), "OK");
}
}
private async void MyMapView_GeoViewTapped(object sender, Esri.ArcGISRuntime.Maui.GeoViewInputEventArgs e)
{
try
{
// Perform the identify operation
IdentifyLayerResult myIdentifyResult = await MyMapView.IdentifyLayerAsync(_wmsLayer, e.Position, 20, false);
// Return if there's nothing to show
if (myIdentifyResult.GeoElements.Count < 1)
{
return;
}
// Retrieve the identified feature, which is always a WmsFeature for WMS layers
WmsFeature identifiedFeature = (WmsFeature)myIdentifyResult.GeoElements[0];
// Retrieve the WmsFeature's HTML content
string htmlContent = identifiedFeature.Attributes["HTML"].ToString();
// Note that the service returns a boilerplate HTML result if there is no feature found.
// This test should work for most arcGIS-based WMS services, but results may vary.
if (!htmlContent.Contains("OBJECTID"))
{
// Return without showing the result
return;
}
// Show a page with the HTML content
await Application.Current.MainPage.Navigation.PushAsync(new WmsIdentifyResultDisplayPage(htmlContent));
}
catch (Exception ex)
{
await Application.Current.MainPage.DisplayAlert("Error", ex.ToString(), "OK");
}
}
}
public class WmsIdentifyResultDisplayPage : ContentPage
{
public WmsIdentifyResultDisplayPage(string htmlContent)
{
Title = "WMS identify result";
// Create the web browser control
Content = new WebView
{
// Display the string content as an HTML document
Source = new HtmlWebViewSource() { Html = htmlContent }
};
}
}
}