Learn how to execute a SQL query to return features A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more from a feature layer A feature layer (server-side) is a spatially-enabled table in a feature service. All features in a feature layer share the same geometry type and set of fields. Learn more based on spatial and attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more criteria.

query a feature layer

A feature layer A feature layer (server-side) is a spatially-enabled table in a feature service. All features in a feature layer share the same geometry type and set of fields. Learn more can contain a large number of features A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more stored in ArcGIS. You can query a layer to access a subset of its features using any combination of spatial and attribute Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more criteria. You can control whether or not each feature’s geometry A geometry is a geometric shape, such as a point, polyline, or polygon, that contains one or more coordinates and a spatial reference. Learn more is returned, as well as which attributes are included in the results. Queries allow you to return a well-defined subset of your hosted data for analysis or display in your app.

In this tutorial, you’ll write code to perform SQL queries that return a subset of features A feature is a single record, also known as a row, that represents a real-world entity. It typically contains a geometry (point, multipoint, polyline, or polygon) and attributes but it can also contain just attributes. Learn more in the LA County Parcel feature layer A feature layer (server-side) is a spatially-enabled table in a feature service. All features in a feature layer share the same geometry type and set of fields. Learn more (containing over 2.4 million features). Features that meet the query criteria are selected in the map.

Prerequisites

Before starting this tutorial:

Optionally, you may want to install the ArcGIS Maps SDK for .NET to get access to project templates in Visual Studio (Windows only) and offline copies of the NuGet packages.

Develop or download

You have two options for completing this tutorial:

  1. Option 1: Develop the code or
  2. Option 2: Download the completed solution

Option 1: Develop the code

To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS Basemap Styles service The ArcGIS Basemap Styles service, also referred to as the Basemap Styles service, is a location service that provides basemap styles and data for the world. It returns styles as Mapbox styles and web maps, and data as vector tiles and/or map tiles. It supports all of the styles in the ArcGIS Basemap style and Open Basemap style family. An ArcGIS Location Platform or ArcGIS Online account is required to use the service. Learn more .

Open a Visual Studio solution

  1. Open the Visual Studio solution you created by completing the Display a map tutorial.
  2. Continue with the following instructions to execute a SQL query to return features from a feature layer based on spatial and attribute criteria.

Update the tutorial name used in the project (optional)

The Visual Studio solution, project, and the namespace for all classes currently use the name DisplayAMap. Follow the steps below if you prefer the name to reflect the current tutorial. These steps are not required, your code will still work if you keep the original name.

Add UI for selecting a predefined query expression

To make performing a query on a feature layer more flexible, add a ComboBox control to present a list of predefined attribute queries for the parcels dataset. While editing this file, also modify the MapView control to bind its SelectionProperties to a property in the view model (so you can set the color used to display selected parcels).

  1. In the Visual Studio > Solution Explorer, double-click the MainWindow.xaml file to open it.

  2. Add XAML that defines a ComboBox control and its behavior.

    • The control is positioned above the map view in the upper-left corner.
    • A list of ComboBoxItems shows predefined expression choices.
    • The first combo box item instructs the user to choose an expression that will be selected when the app initializes.
    • Changes in the selected expression will be handled by the QueryComboBox_SelectionChanged event handler.

    Also modify the MapView control to bind the SelectionProperties property.

    MainWindow.xaml
    14 collapsed lines
    <Window x:Class="QueryAFeatureLayerSQL.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:QueryAFeatureLayerSQL"
    xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
    <local:MapViewModel x:Key="MapViewModel" />
    </Window.Resources>
    <Grid>
    <esri:MapView x:Name="MainMapView"
    Map="{Binding Map, Source={StaticResource MapViewModel}}"
    SelectionProperties="{Binding SelectionProps, Source={StaticResource MapViewModel}}"/>
    <ComboBox x:Name="QueryComboBox"
    SelectionChanged="QueryComboBox_SelectionChanged"
    SelectedIndex="0"
    SelectedValuePath="Content"
    HorizontalAlignment="Left" VerticalAlignment="Top"
    Margin="20" Padding="30,10">
    <ComboBoxItem>Choose a SQL where clause</ComboBoxItem>
    <ComboBoxItem>UseType = 'Government'</ComboBoxItem>
    <ComboBoxItem>UseType = 'Residential'</ComboBoxItem>
    <ComboBoxItem>UseType = 'Irrigated Farm'</ComboBoxItem>
    <ComboBoxItem>TaxRateArea = 10853</ComboBoxItem>
    <ComboBoxItem>TaxRateArea = 10860</ComboBoxItem>
    <ComboBoxItem>Roll_LandValue &gt; 1000000</ComboBoxItem>
    <ComboBoxItem>Roll_LandValue &lt; 1000000</ComboBoxItem>
    </ComboBox>
    </Grid>
    2 collapsed lines
    </Window>
  3. In the section for the combo box you just added, right-click on the name of the event handler text (“QueryComboBox_SelectionChanged”) and choose Go To definition from the context menu. Visual Studio will open the MapWindows.xaml.cs file with the stub for the new QueryComboBox_SelectionChanged() function.

Add code to call the selected query for the current map extent

When the user chooses an expression in the combo box, call a function to execute the query.

The function to execute the query takes three arguments: the ID for the layer to query (string), a SQL expression that defines attribute criteria (string), and the area of the MapView currently being viewed (Envelope).

  1. In the QueryComboBox_SelectionChanged() function: modify the method signature to add the async keyword.

    MainWindow.xaml.cs
    private async void QueryComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    }
  2. Again, in the QueryComboBox_SelectionChanged() function: add code to gather the information required to perform the query, then call the QueryFeatureLayer function (that you will write in a coming step).

    MainWindow.xaml.cs
    43 collapsed lines
    // 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
    //
    // https://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 System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using Esri.ArcGISRuntime.Geometry;
    using Esri.ArcGISRuntime.Mapping;
    namespace QueryAFeatureLayerSQL
    {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
    InitializeComponent();
    }
    private async void QueryComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    // Since the first choice in the combo box are instructions for the app
    // (not actual SQL where clause syntax), ignore it.
    if (QueryComboBox.SelectedIndex != 0)
    {
    // Get the view model using the ID given for the static resource in the XAML.
    var currentMapViewModel = this.FindResource("MapViewModel") as MapViewModel;
    // Get the current view point extent.
    var currentExtent = MainMapView?.GetCurrentViewpoint(ViewpointType.BoundingGeometry)?.TargetGeometry as Envelope;
    // Define the string ID for the feature layer to query.
    string featureLayerId = "Parcels";
    // Define the SQL query where clause to apply to the feature layer.
    // Several SQL query strings were pre-populated in the combo box.
    // This line of code gets the selected choice from the combo box
    // and assigns it to the SQL query string.
    object selectedValue = QueryComboBox.SelectedValue;
    var sqlQuery = selectedValue?.ToString();
    // Call the function in the view model that queries a feature layer. Pass in the:
    // (1) feature layer ID
    // (2) specific SQL syntax for the feature layer
    // (3) current map extent
    if (!string.IsNullOrEmpty(sqlQuery) && currentExtent != null)
    {
    await currentMapViewModel!.QueryFeatureLayer(featureLayerId, sqlQuery, currentExtent);
    }
    }
    }
    4 collapsed lines
    }
    }

Add the parcels layer to the map and set selection properties

You now need to begin working in a different code file within this project.

First, add the LA parcels FeatureLayer to the map’s collection of data layers (GeoModel.OperationalLayers). Providing the Layer.Id allows for referencing the parcels layer from the layer collection when needed. Define the selection color via the map view’s SelectionProperties to distinguish selected features in the map.

  1. In the Visual Studio > Solution Explorer, double-click MapViewModel.cs to open the file.

  2. Add additional required using statements at the top of the class. These make your code more concise and allow you to use classes from these namespaces without having to fully qualify them.

    MapViewModel.cs
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Esri.ArcGISRuntime.Geometry;
    using Esri.ArcGISRuntime.Mapping;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using Esri.ArcGISRuntime.Data;
    using Esri.ArcGISRuntime.UI;
    using System.Threading.Tasks;
  3. Just after the section of code that defines the Map public property, create a similar SelectionProps public property as follows.

    MapViewModel.cs
    private SelectionProperties? _selectionProps;
    public SelectionProperties? SelectionProps {
    get { return _selectionProps; }
    set
    {
    _selectionProps = value;
    OnPropertyChanged();
    }
    }
  4. Add code to the SetupMap() function that adds the parcels feature layer to the map and sets the selection properties.

    MapViewModel.cs
    private void SetupMap()
    {
    // Create a new map with a 'topographic vector' basemap.
    Map map = new Map(BasemapStyle.ArcGISTopographic);
    // Set the initial viewpoint around the Santa Monica Mountains in California.
    var mapCenterPoint = new MapPoint(-118.805, 34.027, SpatialReferences.Wgs84);
    map.InitialViewpoint = new Viewpoint(mapCenterPoint, 100000);
    // Set the view model's Map property with the map.
    Map = map;
    // Add a layer that shows parcels for Los Angeles County.
    Uri parcelsUri = new Uri("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0");
    FeatureLayer parcelsFeatureLayer = new FeatureLayer(parcelsUri);
    // Give the layer an ID so we can easily find it later, then add it to the map.
    parcelsFeatureLayer.Id = "Parcels";
    Map.OperationalLayers.Add(parcelsFeatureLayer);
    // Create selection properties (bound to the MapView).
    SelectionProperties selectionProps = new SelectionProperties();
    selectionProps.Color = System.Drawing.Color.Yellow;
    this.SelectionProps = selectionProps;
    }

Create a function to query the parcels layer and select the result

In this step, create a new function that queries a FeatureLayer (identified using its ID) using both attribute and spatial criteria. After clearing any currently selected features, a new query will be executed to find features in the map’s current extent that meet the selected attribute expression. The features in the FeatureQueryResult will be selected in the parcels layer.

  1. Add the following new method named QueryFeatureLayer() just after the SetupMap() method.

    MapViewModel.cs
    90 collapsed lines
    // 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
    //
    // https://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 System;
    using System.Collections.Generic;
    using System.Text;
    using Esri.ArcGISRuntime.Geometry;
    using Esri.ArcGISRuntime.Mapping;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using Esri.ArcGISRuntime.Data;
    using Esri.ArcGISRuntime.UI;
    using System.Threading.Tasks;
    namespace QueryAFeatureLayerSQL
    {
    class MapViewModel : INotifyPropertyChanged
    {
    public MapViewModel()
    {
    SetupMap();
    }
    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    private Map? _map;
    public Map? Map
    {
    get { return _map; }
    set
    {
    _map = value;
    OnPropertyChanged();
    }
    }
    private SelectionProperties? _selectionProps;
    public SelectionProperties? SelectionProps {
    get { return _selectionProps; }
    set
    {
    _selectionProps = value;
    OnPropertyChanged();
    }
    }
    private void SetupMap()
    {
    // Create a new map with a 'topographic vector' basemap.
    Map map = new Map(BasemapStyle.ArcGISTopographic);
    // Set the initial viewpoint around the Santa Monica Mountains in California.
    var mapCenterPoint = new MapPoint(-118.805, 34.027, SpatialReferences.Wgs84);
    map.InitialViewpoint = new Viewpoint(mapCenterPoint, 100000);
    // Set the view model's Map property with the map.
    Map = map;
    // Add a layer that shows parcels for Los Angeles County.
    Uri parcelsUri = new Uri("https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/LA_County_Parcels/FeatureServer/0");
    FeatureLayer parcelsFeatureLayer = new FeatureLayer(parcelsUri);
    // Give the layer an ID so we can easily find it later, then add it to the map.
    parcelsFeatureLayer.Id = "Parcels";
    Map.OperationalLayers.Add(parcelsFeatureLayer);
    // Create selection properties (bound to the MapView).
    SelectionProperties selectionProps = new SelectionProperties();
    selectionProps.Color = System.Drawing.Color.Yellow;
    this.SelectionProps = selectionProps;
    }
    public async Task QueryFeatureLayer(string layerId, string whereExpression, Envelope queryExtent)
    {
    // Get the layer based on its Id.
    var featureLayerToQuery = _map?.OperationalLayers[layerId] as FeatureLayer;
    // Get the feature table from the feature layer.
    var featureTableToQuery = featureLayerToQuery?.FeatureTable;
    if(featureTableToQuery == null) { return; }
    // Clear any existing selection.
    featureLayerToQuery?.ClearSelection();
    // Create the query parameters using the where expression and extent passed in.
    QueryParameters queryParams = new QueryParameters
    {
    Geometry = queryExtent,
    ReturnGeometry = true,
    WhereClause = whereExpression,
    };
    // Query the table and get the list of features in the result.
    var queryResult = await featureTableToQuery.QueryFeaturesAsync(queryParams);
    // Loop over each feature from the query result.
    foreach (Feature feature in queryResult)
    {
    // Select each feature.
    featureLayerToQuery!.SelectFeature(feature);
    }
    }
    3 collapsed lines
    }
    }
  2. Click Debug > Start Debugging (or press <F5> on the keyboard) to run the app. If your app uses user authentication, enter your ArcGIS Online credentials when prompted.

The app loads with the map centered on the Santa Monica Mountains in California with the parcels feature layer displayed. Choose an attribute expression, and parcels in the current extent that meet the selected criteria will display in the specified selection color.

Alternatively, you can download the tutorial solution, as follows.

Option 2: Download the solution

  1. Click the Download solution link in the right-hand panel of the page.

  2. Unzip the file to a location on your machine.

  3. Open the .sln file in Visual Studio.

Since the downloaded solution does not contain authentication credentials, you must first set up authentication to create credentials, and then add the developer credentials to the solution.

Set up authentication

To access the secure ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more used in this tutorial, you must implement API key authentication API key authentication is a type of authentication that uses an API key to authenticate requests to ArcGIS services and secure portal items. Learn more or user authentication User authentication is a type of authentication that allows users with an ArcGIS account to sign into an application and allow it to access ArcGIS content, services, and resources on their behalf. The typical authorization protocol used is OAuth2.0. Learn more using an ArcGIS Location Platform An ArcGIS Location Platform account, formerly known as an ArcGIS Developer account, is an identity associated with an ArcGIS Location Platform subscription. Learn more or an ArcGIS Online An ArcGIS Online account, also known as an ArcGIS Organization account, is an identity associated with an ArcGIS Online subscription. It can be used to access ArcGIS tools and develop applications with ArcGIS location services for an organization. Learn more account.

To complete this tutorial, click on the tab in the switcher below for your authentication type of choice, either API key authentication or User authentication.

Create a new API key access token An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. Learn more with privileges Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more to access the secure resources used in this tutorial.

  1. Complete the Create an API key tutorial and create an API key with the following privilege(s) Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more :

    • Privileges
      • Location services > Basemaps
  2. Copy and paste the API key access token into a safe location. It will be used in a later step.

Set developer credentials in the solution

To allow your app users to access ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more , use the developer credentials that you created in the Set up authentication step to authenticate requests for resources.

  1. In Visual Studio, in the Solution Explorer, click App.xaml.cs to open the file.

  2. Set the ArcGISEnvironment.ApiKey property with your API key access token.

    App.xaml.cs
    protected override void OnStartup(StartupEventArgs e)
    {
    base.OnStartup(e);
    // Set the access token for ArcGIS Maps SDK for .NET.
    Esri.ArcGISRuntime.ArcGISRuntimeEnvironment.ApiKey = "YOUR_ACCESS_TOKEN";
    // Call a function to set up the AuthenticationManager for OAuth.
    UserAuth.ArcGISLoginPrompt.RegisterOAuthConfig();
    }
  3. Remove the code that sets up user authentication.

    App.xaml.cs
    protected override void OnStartup(StartupEventArgs e)
    {
    base.OnStartup(e);
    // Set the access token for ArcGIS Maps SDK for .NET.
    Esri.ArcGISRuntime.ArcGISRuntimeEnvironment.ApiKey = "YOUR_ACCESS_TOKEN";
    // Call a function to set up the AuthenticationManager for OAuth.
    UserAuth.ArcGISLoginPrompt.RegisterOAuthConfig();
    }

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Run the solution

Click Debug > Start Debugging (or press <F5> on the keyboard) to run the app. If your app uses user authentication, enter your ArcGIS Online credentials when prompted.

The app loads with the map centered on the Santa Monica Mountains in California with the parcels feature layer displayed. Choose an attribute expression, and parcels in the current extent that meet the selected criteria will display in the specified selection color.

What’s next?

Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: