Selecting features in a map widget

Features drawn in the map of a map widget can be selected by the user if they are part of a layer that is configured to also provide a selection data source.Selections can be made by tapping or clicking on the feature in the map, or by using the Select map tool. Selected features are shown by a highlight symbol drawn around the selected feature(s).

Using the ESRI.ArcGIS.Client API, features can also be selected programmatically, in any feature layer in the map. However, Operations Dashboard for ArcGIS allows the author of an operation view to specifically control which layers in the map have selectable features by checking the Selectable check box in the Data Sources tab of theConfigure Map dialog box. In this way, only specific layers are selectable in the application. The sections below describe how to select features, and also how to restrict selections to only the layers configured as Selectable by the author.

Selecting features programmatically

Features in any feature layer in a map can also be selected programmatically by an add-in, by using the Map property of a MapWidget:

  1. Get the required feature layers from the Map via the AcceleratedDisplayLayers collection. See the Working with the Map topic for more information.
  2. Get the ESRI.ArcGIS.Client.Graphic object representing the required feature(s) from the Graphics property on the feature layer.
  3. Use the Select method on the ESRI.ArcGIS.Client.Graphic class to select the feature.

For more general information about selecting features using the WPF API, refer to samples in the Samples Browser.

Selectable layers defined by the application

A layer is configured to be a selection data source in the Configure Map dialog box by checking the Selectable check box, as described above. When a layer is confgured to be selectable in this way, a second data source is created representing only the features currently selected in the layer. This second data source will return True from the DataSource.IsSelectable property. For more information about selectable data sources, see the Working with data sources topic.

Although it is possible to programmatically select features in any feature layer in the map, it is generally recommended that only features in layers configured to be selectable are selected programmatically. This ensures that the user experience of selecting features is consistent.

The code snippets below demonstrate a way to assess if a layer in a map is configured to be selectable, by finding if there is a DataSource based on the same Client FeatureLayer that returns True from the IsSelectable property.

Finding if a feature layer is selectable in the map

// Find the map layer in the map widget that contains the data source
MapWidget mapW = MapWidget.FindMapWidget(dataSrc);
if (mapW != null)
{
  // Get the feature layer in the map for the data source.
  client.FeatureLayer featureL = mapW.FindFeatureLayer(dataSrc);
       
  // Find the Selectable data sources provided by feature layers in the map widget.
  var dataSourcesFromSameWidget = OperationsDashboard.Instance.DataSources.Select((dataSource) =>
  {
    client.FeatureLayer fl = mapW.FindFeatureLayer(dataSource);
    return ((fl != null) && (dataSource.IsSelectable)) ? fl : null;
  });

  if (!dataSourcesFromSameWidget.Contains(featureL))
    return;

  // For each result feature, find the corresponding graphic in the map.
  foreach (client.Graphic feature in featureL.Graphics)
  {
    // Here, perform logic to determine if this graphic should be selected or not.
    // Use feature.Select() and feature.Unselect to select and unselect features.
  }
}

Finding if a feature layer is selectable in the map

' Find the map layer in the map widget that contains the data source.
Dim mapW As MapWidget = MapWidget.FindMapWidget(dataSrc)
If (Not mapW Is Nothing) Then
  ' Get the feature layer in the map for the data source.
  Dim featureL As client.FeatureLayer = mapW.FindFeatureLayer(dataSrc)

  ' Find the Selectable data sources provided by feature layers in the map widget.
  Dim dataSourcesFromSameWidget = OperationsDashboard.Instance.DataSources.Select(Function(dataSource)
      Dim fl As client.FeatureLayer = mapW.FindFeatureLayer(dataSource)
      If ((Not fl Is Nothing) AndAlso (dataSource.IsSelectable)) Then
        Return fl
      Else
        Return Nothing
      End If
      End Function)

  If (Not dataSourcesFromSameWidget.Contains(featureL)) Then
    Return
  End If

  ' For each result feature, find the corresponding graphic in the map.
  Dim feature As client.Graphic
  For Each feature In featureL.Graphics
    ' Here, perform logic to determine if this graphic should be selected or not.
    ' Use feature.Select() and feature.Unselect to select and unselect features.
  Next
End If
CautionCaution:

If features are programmatically selected that are not part of a selectable data source in the application, the only way they can be unselected again is by other custom code. Selecting other features interactively using the system functionality will not change selections made on layers that are not configured as Selectable.

Selecting features based on results of a query

In some cases, the features to be selected may be based on the results of a call to one of the asynchronous query methods on the DataSource class. In this case, it is important to note that the features returned in the QueryResult are copies, and not the same objects are the features in the feature layer, and therefore selecting the copies returned from the query will not select the features displayed in the map.

The code snippets below demonstrate how you can select features in a feature layer in a map based on the results of a query, by finding the features in the feature layer with a matching ObjectId to the copies returned from the query.

Select features based on query results

QueryResult result = await dataSrc.ExecuteQueryAsync(new Query(queryWhereClause, new string[] { dataSrc.ObjectIdFieldName }));
if ((result == null) || (result.Canceled) || (result.Features == null) || (result.Features.Count < 1))
  return;

// Get the array of IDs from the query results.
var resultOids = from feature in result.Features select System.Convert.ToInt32(feature.Attributes[dataSrc.ObjectIdFieldName]);

// Find the map layer in the map widget that contains the data source.
MapWidget mapW = MapWidget.FindMapWidget(dataSrc);
if (mapW != null)
{
  // Get the feature layer in the map for the data source.
  client.FeatureLayer featureL = mapW.FindFeatureLayer(dataSrc);
       
  // NOTE: Can check here if the feature layer is selectable, using code shown above.

  // For each result feature, find the corresponding graphic in the map by OID and select it.
  foreach (client.Graphic feature in featureL.Graphics)
  {
    int featureOid;
    int.TryParse(feature.Attributes[dataSrc.ObjectIdFieldName].ToString(), out featureOid);
    if (resultOids.Contains(featureOid))
    {
      feature.Select();
    }
  }
}

Select features based on query results

Dim result As QueryResult = Await dataSrc.ExecuteQueryAsync(New Query(queryWhereClause, New String() {dataSrc.ObjectIdFieldName}))
If ((result Is Nothing) OrElse (result.Canceled) OrElse (result.Features Is Nothing) OrElse (result.Features.Count < 1)) Then
  Return
End If
' Get the array of IDs from the query results.
Dim resultOids = From feature In result.Features Select System.Convert.ToInt32(feature.Attributes(dataSrc.ObjectIdFieldName))
' Find the map layer in the map widget that contains the data source.
Dim mapW As MapWidget = MapWidget.FindMapWidget(dataSrc)
If (Not mapW Is Nothing) Then
  ' Get the feature layer in the map for the data source.
  Dim featureL As client.FeatureLayer = mapW.FindFeatureLayer(dataSrc)

  ' NOTE: Can check here if the feature layer is selectable, using code shown above.

  ' For each result feature, find the corresponding graphic in the map by OID and select it.
  Dim feature As client.Graphic
  For Each feature In featureL.Graphics
    Dim featureOid As Integer
    Integer.TryParse(feature.Attributes(dataSrc.ObjectIdFieldName).ToString(), featureOid)
    If (resultOids.Contains(featureOid)) Then
      feature.Select()
    End If
  Next
End If

Refreshing selection data source consumers

Selecting features programmatically updates the selection data source in the same way as when a user selects features interactively. Any widgets configured against the selection data source will receive a call to IDataSourceConsumer.OnRefresh when the selection is changed programmatically.

Related topics

Working with the Map

Adding temporary graphics

How to respond to changes in data sources

1/27/2015