ArcGIS Runtime SDK for .NET

Edit features

ArcGIS Runtime supports editing workflows that leverage the use of features. A feature is a persisted piece of data (essentially a row in a table) that includes a geographic location (shape) as well as attributes that further describe it, such as Name, Area, Population, ZoningCode, and so on. Your app can include the ability to add and delete entire features or to make edits to existing feature geometry and attributes. If your features have attachments (images or text files, for example) or related records in another dataset, that information can be edited as well.

Features can be hosted in an online service, stored locally in a database, or saved in a map or portal item. How your features are stored affects how you make and manage edits to them in your app. For more information on features and where they come from, see Features and graphics.

Editing overview

Your apps can edit features while online (connected to the network and using data hosted online) or offline (without a network connection and using local data). You can edit features from a service, a geodatabase, or a feature collection. For an introduction see Editing. While all editing workflows are described in this topic, note that there is no difference in the code that actually makes the edits (adding, deleting, or updating features, in other words).

Features from an ArcGISFeatureTable return ArcGISFeature objects which implement the loadable pattern for increased efficiency. When fetching ArcGISFeature objects for rendering and query purposes, a minimum set of required fields is returned, such as identifiers, geometry, fields used for symbolizing, and so on. When you want to edit the feature, you must load it first, otherwise the edit operation will fail.

Note:

When querying features from an online service, you have the option to return your results as loaded features so all fields are immediately available and edits can be performed.

Feature editing is supported for a number of workflows. The developer patterns for each is described below:

Tip:

For editing workflows that use a local geodatabase, you can use geodatabase transactions to manage a set of edits (transaction). You can then control when those edits are committed (saved) or rolled back (discarded) as a single unit.

The online feature service editing workflow is:

  1. Create a service feature table from a feature service using the REST endpoint (URL, in other words) to identify the features you want to work with, or open a map which already contains a service feature table via a feature layer.
  2. Perform any edits against the service feature table (add, update, and delete features and feature attachments).
  3. Apply your edits to the feature service right away.

The offline feature service editing workflow is:

  1. Generate a local runtime geodatabase using a sync-enabled feature service while the user is onlineas described in Create an offline map.
  2. Create a geodatabase feature table from the local geodatabase. If this is for a connected feature layer already in a map, then that layer will need to be switched out with a new feature layer created with this table.
  3. Perform any edits against the geodatabase feature table (add, update, and delete features and feature attachments).
  4. Synchronize your edits with the service once you have a network connection, as described in Sync offline edits.

The static feature collection editing workflow is:

  1. Create a new feature collection or open a map which already contains a feature collection via a feature collection layer.
  2. For new feature collections, create a new feature collection table and add it to the feature collection. For feature collections from a map, access a feature collection table from the feature collection.
  3. Perform any edits against the feature collection table (add, update, and delete features).
  4. For feature collections which are to be stored in the map, save the map. For feature collections to be saved as a portal item, save the feature collection as a portal item.

Create a feature table

Before you can edit features, you need to obtain feature data from a feature table.

In a connected workflow, the type of feature table you use and edit is a ServiceFeatureTable. In a disconnected workflow, the type of feature table you use and edit is a GeodatabaseFeatureTable. Both classes inherit from ArcGISFeatureTable, which itself inherits from FeatureTable.

The class hierarchy between these is as follows:

Feature table classes

For working with features by value, the type of table you use is FeatureCollectionTable. Feature collection tables do not contain attachments and inherit directly from FeatureTable.

The methods to add, update, and delete features are common to FeatureTable and the methods for updating attachments are provided by ArcGISFeatureTable. Therefore, all the methods you have at your disposal to edit features from a feature service are available both online and offline. The ServiceFeatureTable used in connected editing provides additional methods to apply feature edits and attachment edits back to the service. You should apply any edits to the service as soon as you have made them on your feature table.

Feature service edit capabilities

When working with features from a feature service online or offline, additional edit capabilities are defined to allow or prevent certain types of edits to features. You should check these capabilities to determine what editing capability is available. You may also need to verify ownership-based access is available for each edit you want to complete.

You can use properties on a feature table to find out what type of editing is supported.

  • Is editable: indicates if the table is editable.
  • Edit capabilities: describes the types of edits that are allowed for the table, such as adding, deleting, or updating features, for example.
A feature service might also use ownership-based access control, which means edits to particular features are only available to certain users. You can check ownership-based access using properties on the feature table.
  • Can add: whether or not the current user can add a feature to the table.
  • Can delete: whether or not the current user can delete a feature from the table.
  • Can update: whether or not the current user can edit an existing feature.

Online feature services

In an online workflow, you need a service feature table (ServiceFeatureTable class) created from a feature service. If you have opened a map, you can use a feature layer and retrieve its feature table and check it is of the correct type. For new layers, you can create a service feature table with the feature service URL and then create a feature layer. Once the feature layer is in a map and displayed in a map view, features in the map extent are added to the service feature table and can be edited. As you pan and zoom the map (that is, change the map extent), more features are retrieved from the feature service and added to the service feature table. If you are not using a map or you want to pre-populate your table with a fixed set of features, use the populateFromService method.

Note:

The number of features you see when you initially visit a new area of the map is limited by the feature service's maximum record count property (the default value for this property is 1,000). Pan and zoom to query the service for more features. Once features are retrieved from the service and visible in your map, they are available in your service feature table for editing and querying.

Use code like the following code to instantiate a new service feature table from a URL.

// create a new geodatabase feature service table
var featureTableUri = new System.Uri("http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0");
var table = new ServiceFeatureTable(featureTableUri);

Because they rely on a remote service to properly initialize their state, service feature tables use the Loadable pattern. You can load a service feature table and check its load status before adding it to the map, which allows you to handle load failure and to retry loading the table if necessary. However, if you use the feature table to create a feature layer and add that to a map or scene, the table will automatically attempt to load when the layer is displayed.

Note:

Features in a service feature table are Loadable for added efficiency; before editing your feature ensure it is loaded otherwise the edit operation will fail.

Offline feature services

In an offline workflow, you need to first generate a runtime geodatabase from a sync-enabled feature service while you have a network connection. Follow the geodatabase generation process described in Create an offline map. This process results in a geodatabase stored locally on disk. The geodatabase contains one or more feature tables, one for each service layer or service table that you requested in the geodatabase generation process. When offline, create geodatabase feature tables (GeodatabaseFeatureTable class) from the geodatabase, for example, on application load. The features stored in the geodatabase tables are available for editing whether you display them in a layer or not, but in most cases you'll want to create feature layers to display them for editing. Also, consider generating an offline basemap to give the feature data some geographical context when your users edit offline.

Caution:

You can also generate a runtime geodatabase using ArcGIS for Desktop, but these geodatabases are read-only.

The following example shows several ways to get a feature table from a local geodatabase:

// open a local geodatabase
var gdb = await Esri.ArcGISRuntime.Data.Geodatabase.OpenAsync(gdbPath);


// get the first table in the database
var table = gdb.GeodatabaseFeatureTables.FirstOrDefault();


// get the third table
var anotherTable = gdb.GeodatabaseFeatureTables.ElementAt(2);


// find a table by name
var marineTable = gdb.GeodatabaseFeatureTables.FirstOrDefault(t => t.TableName == "Marine");


// loop through all tables
foreach (var t in gdb.GeodatabaseFeatureTables)
{
    // ... code here to work with the table ...
}

Static feature collections

For working with static feature collections, you either need a map which already contains a feature collection layer, or you need to create a new feature collection layer.

To create a new feature collection layer with a feature collection:

// Open a portal item containing a feature collection
var portal = await ArcGISPortal.CreateAsync();
var collectionItem = await PortalItem.CreateAsync(portal, itemId);


// Verify that the item is a feature collection
if (collectionItem.Type == PortalItemType.FeatureCollection)
{
    // Create a new FeatureCollection from the item
    var featureCollection = new FeatureCollection(collectionItem);
         // Create a layer to display the collection and add it to the map as an operational layer
    var featureCollectionLayer = new FeatureCollectionLayer(featureCollection);
    featureCollectionLayer.Name = collectionItem.Title;
    MyMapView.Map.OperationalLayers.Add(featureCollectionLayer);
}

Add layers to the map

You can display the features contained in the feature table by adding them to a feature layer in the map. Create feature layers from any feature table then add them to a map. A feature layer, once added to a map, takes care of displaying the features contained in your feature table within the map extent currently displayed. When features in the table are edited, the edits are visible right away in the associated feature layer, but not immediately committed back to the feature source.

The following example calls LoadAsync, then checks the LoadStatus to verify the table was loaded successfully from the service or geodatabase. It then creates a layer from the feature table and adds it to the map.

// load the feature table
await table.LoadAsync();


// if the table was loaded successfully, create a new feature layer for the table and add it to the map
if (table.LoadStatus == Esri.ArcGISRuntime.LoadStatus.Loaded)
{
    var lyr = new FeatureLayer(table);
    MyMapView.Map.OperationalLayers.Add(lyr);
}

You will be able to see features like this on your map.

Features displayed on the map.

Add features

For creating new features, it's common for an app to allow the user to click the map to specify a new feature's location. You can provide this capability by listening to a click event on your map view, which in turn will call a function for adding a new feature.

private void MyMapView_GeoViewTapped(object sender, Esri.ArcGISRuntime.UI.Controls.GeoViewInputEventArgs e)
{
    // get the click point in geographic coordinates
    var mapClickPoint = e.Location;


    // call a function that will add a new feature at this location
    AddDamageFeature(mapClickPoint, "Minor", "Earthquake");
}

To add features to a feature table, create a new feature from geometry (for example, point, line, or polygon), create attributes for the new feature, and then call add feature. This adds the feature to a table stored locally on your device. Even if you're editing a service feature table, your edits are initially stored in a table on the client. You must explicitly apply service feature table edits to commit them to the parent feature service.

Note:

All features you add or update in a feature service should have valid geometry. Creating features with empty (null) geometry can cause unexpected issues when working with features in ArcGIS Runtime offline editing workflows.

private async void AddDamageFeature(MapPoint structureLocation, string type, string cause)
{
    var attributes = new Dictionary<string, object>();
    attributes.Add("typdamage", type);
    attributes.Add("primcause", cause);


    // create a new feature in the damage table, pass in the attributes and geometry
    var newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    // add the new feature (this updates the local copy of the table)
    await _damagePointsTable.AddFeatureAsync(newFeature);


    // push this update (apply edits) to the feature service
    IReadOnlyList<EditResult> editResults = await _damagePointsTable.ApplyEditsAsync();
    // check the results for errors
    foreach (var r in editResults)
    {
        if (r.CompletedWithErrors)
        {
            Console.WriteLine("Edit to Object '" + r.ObjectId + "' failed: " + r.Error.Message);
        }
    }
}

Tip:

When adding new features, it is good practice to ensure the geometry of the new feature is not null. If the location of a feature is not yet known, you may want to use an empty geometry.

Select features

In an editing app, a common workflow is for the user to choose features to edit by selecting them with a query or interactively on the map. Features in a feature layer can be selected, which results in them being highlighted in the map view. You can select features based on spatial relationships (sample points located inside the forest boundary polygon), using attribute criteria (pipes with a material_type attribute of 'pvc'), or both (parcels outside the city limits with a zoning code of 'COM'). You can also get selected features from a layer, after letting the user make an interactive or custom selection, for example.

Selected point graphics

In editing workflows, features are typically selected for tasks such as deleting or updating.

// Build a buffer (polygon) around a click point
var buffer = GeometryEngine.Buffer(queryPoint, 5000);


// Use the buffer to define the geometry for a query
var query = new QueryParameters();
query.Geometry = buffer;
query.SpatialRelationship = SpatialRelationship.Contains;


// Select features in a feature layer using the query
await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);

You can also select specific features using the select feature method and passing in a single feature.

Update features

Feature updates include moving or reshaping a feature's geometry or making edits to attribute values. As with all editing operations the changes are not automatically committed to the features source, it is the developer's responsibility to do this.

// get all selected features in the layer
var damageLayer = MyMapView.Map.OperationalLayers[0] as FeatureLayer;
var selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();


// loop thru all features in the selection
foreach (ArcGISFeature f in selectedFeatures)
{
    // load the feature
    await f.LoadAsync();


    // update the damage type attribute
    f.Attributes["typdamage"] = "Inaccessible";


    // get the feature's geometry (point), move it to the north
    var location = f.Geometry as MapPoint;
    var newLocation = new MapPoint(location.X, location.Y + 50000);


    // set the feature's new location
    f.Geometry = newLocation;


    // update the feature in the local cache with these edits
    await _damagePointsTable.UpdateFeatureAsync(f);
}


// apply all the edits back to the service feature table
var editResults = await _damagePointsTable.ApplyEditsAsync();

Delete features

You can delete several features from a feature table using the delete features method that accepts a list of features, or just a single feature with a call to delete feature. As with all editing operations the changes are not automatically committed to the features source, it is the developer's responsibility to do this.

// get all selected features in the layer
var damageLayer = MyMapView.Map.OperationalLayers[0] as FeatureLayer;
var selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();


// delete the selected features from the local cache
await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);


// apply all the edits back to the service feature table
var editResults = await _damagePointsTable.ApplyEditsAsync();

Feature attachments

Attachments are files you associate with a feature, including text, images, videos, and so on. Attachments are only available for features from an ArcGIS feature table. You might want to attach a photograph to a parcel feature, for example, to show a picture of the property. Attachments on a feature are manipulated using the following methods on the ArcGIS feature class.

MethodDescription

add attachment

Adds a new attachment to a feature

delete attachment

Deletes a single existing attachment

delete attachments

Deletes a list of existing attachments

update attachment

Updates an existing attachment

fetch attachments

Accesses the attachments for a feature

ArcGIS feature inherits from the feature class, so you can cast from feature to ArcGIS feature if needed. Prior to adding, updating or deleting features it is good practice to make sure that you have permission to perform one of these operations. This is done by using the can edit attachments property. Once you have performed your attachment edits, these are applied to the feature using the update feature method and finally the feature needs to be applied to the service by calling the apply edits method on your feature table.

// cast to ArcGISFeature to add attachments
ArcGISFeature agsFeature = (ArcGISFeature)feature;


// load the feature
await agsFeature.LoadAsync();


// add an attachment - pass the name, mime type, and attachment data (bytes, e.g.)
await agsFeature.AddAttachmentAsync("AssessmentImaqe.jpg", "image/jpg", imageData);


// save the attachment with the feature
await _damagePointsTable.UpdateFeatureAsync(agsFeature);


//commit update operation
IReadOnlyList<EditResult> results = await _damagePointsTable.ApplyEditsAsync();


// check edits for errors
var errs = from e in results where e.CompletedWithErrors select e;
foreach (var err in errs)
{
    // process errors here
}

Related topics