Skip to content

ProSnippets Editing

arcgisprosdk edited this page Jan 12, 2017 · 21 revisions
Language:              C#  
Subject:               Editing  
Contributor:           ArcGIS Pro SDK Team <[email protected]>  
Organization:          Esri, http://www.esri.com  
Date:                  1/5/2017  
ArcGIS Pro:            1.4  
Visual Studio:         2013, 2015  
.NET Target Framework: 4.6.1  

##Find edit template by name on a layer

ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
  //get the templates
  var map = ArcGIS.Desktop.Mapping.MapView.Active.Map;
  var mainTemplate = map.FindLayers("main").First().GetTemplate("Distribution");
  var mhTemplate = map.FindLayers("Manhole").First().GetTemplate("Active");
});

##Create a feature using the current template

var myTemplate = ArcGIS.Desktop.Editing.Templates.EditingTemplate.Current;
var myGeometry = _geometry;

//Create edit operation and execute
var op = new ArcGIS.Desktop.Editing.EditOperation();
op.Name = "Create my feature";
op.Create(myTemplate, myGeometry);
op.Execute();

##Create feature from modified inspector

ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
  //Create new feature from an existing inspector (copying the feature)
  var op = new ArcGIS.Desktop.Editing.EditOperation();
  op.Name = "Create from insp";
  op.Create(insp.MapMember, insp.ToDictionary(a => a.FieldName, a => a.CurrentValue));
  op.Execute();
});

##Create features from a CSV file

//Run on MCT
ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
  //Create the edit operation
  var createOperation = new ArcGIS.Desktop.Editing.EditOperation();
  createOperation.Name = "Generate points";
  createOperation.SelectNewFeatures = false;

  //Loop through csv data
  foreach (var item in csvData)
  {
    //Create the point geometry
    ArcGIS.Core.Geometry.MapPoint newMapPoint = ArcGIS.Core.Geometry.MapPointBuilder.CreateMapPoint(item.X, item.Y);

    // include the attributes via a dictionary
    var atts = new Dictionary<string, object>();
    atts.Add("StopOrder", item.StopOrder);
    atts.Add("FacilityID", item.FacilityID);
    atts.Add("Shape", newMapPoint);   // I know the shape field is called Shape - but dont assume

    // queue feature creation
    createOperation.Create(layer, atts);
  }

  // execute the edit (feature creation) operation
  return createOperation.Execute();
});

##Search for layer features and update a field

ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
  //find layer
  var disLayer = ArcGIS.Desktop.Mapping.MapView.Active.Map.FindLayers("Distribution mains").FirstOrDefault() as BasicFeatureLayer;

  //Search by attribute
  var queryFilter = new ArcGIS.Core.Data.QueryFilter();
  queryFilter.WhereClause = "CONTRACTOR = 'KCGM'";
  var rc = disLayer.Search(queryFilter);

  //Create list of oids to update
  var oidSet = new List<long>();
  while (rc.MoveNext()) {oidSet.Add(rc.Current.GetObjectID());}

  //Create edit operation and update
  var op = new ArcGIS.Desktop.Editing.EditOperation();
  op.Name = "Update date";
  var insp = new ArcGIS.Desktop.Editing.Attributes.Inspector();
  insp.Load(disLayer, oidSet);
  insp["InspDate"] = "9/21/2013";
  op.Modify(insp);
  op.Execute();
});

##Edit Operation Create Features

var createFeatures = new EditOperation();
createFeatures.Name = "Create Features";
//Create a feature with a polygon
createFeatures.Create(featureLayer, polygon);

//with a callback
createFeatures.Create(featureLayer, polygon, (object_id) => {
    //TODO - use the oid of the created feature
    //in your callback
});

//Do a create features and set attributes
var attributes = new Dictionary<string, object>();
attributes.Add("SHAPE", polygon);
attributes.Add("NAME", "Corner Market");
attributes.Add("SIZE", 1200.5);
attributes.Add("DESCRIPTION", "Corner Market");

createFeatures.Create(featureLayer, attributes);

//Create features using the current template
//Must be within a MapTool
createFeatures.Create(this.CurrentTemplate, polygon);

//Execute to execute the operation
//Must be called within QueuedTask.Run
          createFeatures.Execute();

//or use async flavor
          //await createFeatures.ExecuteAsync();

##Edit Operation Clip Features

var clipFeatures = new EditOperation();
clipFeatures.Name = "Clip Features";
  clipFeatures.Clip(featureLayer, oid, clipPoly, ClipMode.PreserveArea);
  //Execute to execute the operation
  //Must be called within QueuedTask.Run
  clipFeatures.Execute();

  //or use async flavor
  //await clipFeatures.ExecuteAsync();

##Edit Operation Cut Features

var select = MapView.Active.SelectFeatures(clipPoly);

  var cutFeatures = new EditOperation();
  cutFeatures.Name = "Cut Features";
  cutFeatures.Cut(featureLayer, oid, cutLine);

  //Cut all the selected features in the active view
  //Select using a polygon (for example)
  var kvps = MapView.Active.SelectFeatures(polygon).Select(
       k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));
  cutFeatures.Cut(kvps, cutLine);

  //Execute to execute the operation
  //Must be called within QueuedTask.Run
  cutFeatures.Execute();

  //or use async flavor
  //await cutFeatures.ExecuteAsync();

##Edit Operation Delete Features

var deleteFeatures = new EditOperation();
deleteFeatures.Name = "Delete Features";
var table = MapView.Active.Map.StandaloneTables[0];
//Delete a feature in a standalone table
deleteFeatures.Delete(table, oid);

//Delete all the selected features in the active view
//Select using a polygon (for example)
var selection = MapView.Active.SelectFeatures(polygon).Select(
     k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));

deleteFeatures.Delete(selection);

//Execute to execute the operation
//Must be called within QueuedTask.Run
deleteFeatures.Execute();

//or use async flavor
//await deleteFeatures.ExecuteAsync();

##Edit Operation Duplicate Features

var duplicateFeatures = new EditOperation();
duplicateFeatures.Name = "Duplicate Features";

//Duplicate with an X and Y offset of 500 map units
duplicateFeatures.Duplicate(featureLayer, oid, 500.0, 500.0, 0.0);

//Execute to execute the operation
//Must be called within QueuedTask.Run
duplicateFeatures.Execute();

//or use async flavor
//await duplicateFeatures.ExecuteAsync();

##Edit Operation Explode Features

var explodeFeatures = new EditOperation();
explodeFeatures.Name = "Explode Features";

//Take a multipart and convert it into one feature per part
//Provide a list of ids to convert multiple
explodeFeatures.Explode(featureLayer, new List<long>() {oid}, true);

//Execute to execute the operation
//Must be called within QueuedTask.Run
explodeFeatures.Execute();

//or use async flavor
//await explodeFeatures.ExecuteAsync();

##Edit Operation Merge Features

var mergeFeatures = new EditOperation();
mergeFeatures.Name = "Merge Features";

//Merge three features into a new feature using defaults
//defined in the current template
mergeFeatures.Merge(this.CurrentTemplate as EditingFeatureTemplate, featureLayer, new List<long>() { 10, 96, 12 });

//Merge three features into a new feature in the destination layer
mergeFeatures.Merge(destinationLayer, featureLayer, new List<long>() { 10, 96, 12 });
//Use an inspector to set the new attributes of the merged feature
var inspector = new Inspector();
inspector.Load(featureLayer, oid);//base attributes on an existing feature
//change attributes for the new feature
inspector["NAME"] = "New name";
inspector["DESCRIPTION"] = "New description";

//Merge features into a new feature in the same layer using the
//defaults set in the inspector
mergeFeatures.Merge(featureLayer, new List<long>() {10, 96, 12}, inspector);

//Execute to execute the operation
//Must be called within QueuedTask.Run
mergeFeatures.Execute();

//or use async flavor
//await mergeFeatures.ExecuteAsync();

##Edit Operation Modify Features

var modifyFeatures = new EditOperation();
modifyFeatures.Name = "Modify Features";

//use an inspector
var modifyInspector = new Inspector();
modifyInspector.Load(featureLayer, oid);//base attributes on an existing feature
                                        //change attributes for the new feature

modifyInspector["SHAPE"] = polygon;//Update the geometry
modifyInspector["NAME"] = "Updated name";//Update attribute(s)

modifyFeatures.Modify(modifyInspector);

//update geometry and attributes using overload
var featureAttributes = new Dictionary<string, object>();
featureAttributes["NAME"] = "Updated name";//Update attribute(s)
modifyFeatures.Modify(featureLayer, oid, polygon, featureAttributes);

//Execute to execute the operation
//Must be called within QueuedTask.Run
modifyFeatures.Execute();

//or use async flavor
//await modifyFeatures.ExecuteAsync();

##Edit Operation Planarize Features

var planarizeFeatures = new EditOperation();
planarizeFeatures.Name = "Planarize Features";

//Planarize one or more features
planarizeFeatures.Planarize(featureLayer, new List<long>() { oid });

//Execute to execute the operation
//Must be called within QueuedTask.Run
planarizeFeatures.Execute();

//or use async flavor
//await planarizeFeatures.ExecuteAsync();

##Edit Operation Reshape Features

var reshapeFeatures = new EditOperation();
reshapeFeatures.Name = "Reshape Features";

reshapeFeatures.Reshape(featureLayer, oid, modifyLine);

//Reshape a set of features that intersect some geometry....
var selFeatures = MapView.Active.GetFeatures(modifyLine).Select(
    k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));

reshapeFeatures.Reshape(selFeatures, modifyLine);

//Execute to execute the operation
//Must be called within QueuedTask.Run
reshapeFeatures.Execute();

//or use async flavor
//await reshapeFeatures.ExecuteAsync();

##Edit Operation Rotate Features

var rotateFeatures = new EditOperation();
rotateFeatures.Name = "Rotate Features";

//Rotate works on a selected set of features
//Get all features that intersect a polygon
var rotateSelection = MapView.Active.GetFeatures(polygon).Select(
    k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));

//Rotate selected features 90 deg about "origin"
rotateFeatures.Rotate(rotateSelection, origin, Math.PI / 2);

//Execute to execute the operation
//Must be called within QueuedTask.Run
rotateFeatures.Execute();

//or use async flavor
//await rotateFeatures.ExecuteAsync();

##Edit Operation Scale Features

var scaleFeatures = new EditOperation();
scaleFeatures.Name = "Scale Features";

//Rotate works on a selected set of features
var scaleSelection = MapView.Active.GetFeatures(polygon).Select(
    k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));

//Scale the selected features by 2.0 in the X and Y direction
scaleFeatures.Scale(scaleSelection, origin, 2.0, 2.0, 0.0);

//Execute to execute the operation
//Must be called within QueuedTask.Run
scaleFeatures.Execute();

//or use async flavor
//await scaleFeatures.ExecuteAsync();

##Edit Operation SplitAtPoints Features

var splitAtPointsFeatures = new EditOperation();
splitAtPointsFeatures.Name = "SplitAtPoints Features";

var splitPoints = new List<MapPoint>() {mp1, mp2, mp3};

//Split the feature at 3 points
splitAtPointsFeatures.SplitAtPoints(featureLayer, oid, splitPoints);

//Execute to execute the operation
//Must be called within QueuedTask.Run
splitAtPointsFeatures.Execute();

//or use async flavor
//await splitAtPointsFeatures.ExecuteAsync();

##Edit Operation Transform Features

var transformFeatures = new EditOperation();
transformFeatures.Name = "Transform Features";

//Transform a selected set of features
var transformSelection = MapView.Active.GetFeatures(polygon).Select(
    k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));

transformFeatures.Transform(transformSelection, linkLayer);

//Transform just a layer
transformFeatures.Transform(featureLayer, linkLayer);

//Perform an affine transformation
transformFeatures.TransformAffine(featureLayer, linkLayer);

//Execute to execute the operation
//Must be called within QueuedTask.Run
splitAtPointsFeatures.Execute();

//or use async flavor
//await splitAtPointsFeatures.ExecuteAsync();

##Edit Operation Perform a Clip, Cut, and Planarize

//Multiple operations can be performed by a single
//edit operation.
var clipCutPlanarizeFeatures = new EditOperation();
clipCutPlanarizeFeatures.Name = "Clip, Cut, and Planarize Features";
clipCutPlanarizeFeatures.Clip(featureLayer, oid, clipPoly);
clipCutPlanarizeFeatures.Cut(featureLayer, oid, cutLine);
clipCutPlanarizeFeatures.Planarize(featureLayer, new List<long>() { oid});

//Note: An edit operation is a single transaction. 
//Execute the operations (in the order they were declared)
clipCutPlanarizeFeatures.Execute();

//or use async flavor
//await clipCutPlanarizeFeatures.ExecuteAsync();

##Edit Operation Chain Edit Operations

//Chaining operations is a special case. Use "Chained Operations" when you require multiple transactions 
//to be undo-able with a single "Undo".

//The most common use case for operation chaining is creating a feature with an attachement. 
//Adding an attachment requires the object id (of a new feature) has already been created. 
var editOperation1 = new EditOperation();
editOperation1.Name = string.Format("Create point in '{0}'", CurrentTemplate.Layer.Name);

long newFeatureID = -1;
//The Create operation has to execute so we can get an object_id
editOperation1.Create(this.CurrentTemplate, polygon, (object_id) => newFeatureID = object_id);
//Must be within a QueuedTask
editOperation1.Execute();

//or use async flavor
//await editOperation1.ExecuteAsync();

//Now, because we have the object id, we can add the attachment.  As we are chaining it, adding the attachment 
//can be undone as part of the "Undo Create" operation. In other words, only one undo operation will show on the 
//Pro UI and not two.
var editOperation2 = editOperation1.CreateChainedOperation();
//Add the attachement using the new feature id
editOperation2.AddAttachment(this.CurrentTemplate.Layer, newFeatureID, @"C:\data\images\Hydrant.jpg");

//editOperation1 and editOperation2 show up as a single Undo operation on the UI even though
//we had two transactions
//Must be within a QueuedTask
editOperation2.Execute();

//or use async flavor
//await editOperation2.ExecuteAsync();

##Load map selection into Inspector

// get the currently selected features in the map
var selectedFeatures = ArcGIS.Desktop.Mapping.MapView.Active.Map.GetSelection();
// get the first layer and its corresponding selected feature OIDs
var firstSelectionSet = selectedFeatures.First();
// create an instance of the inspector class
var inspector = new ArcGIS.Desktop.Editing.Attributes.Inspector();
// load the selected features into the inspector using a list of object IDs
await inspector.LoadAsync(firstSelectionSet.Key, firstSelectionSet.Value);

##Load the first feature of a layer into the inspector

// get the first feature layer in the map
var firstFeatureLayer = ArcGIS.Desktop.Mapping.MapView.Active.Map.GetLayersAsFlattenedList().
    OfType<ArcGIS.Desktop.Mapping.FeatureLayer>().FirstOrDefault();
// create an instance of the inspector class
var inspector = new ArcGIS.Desktop.Editing.Attributes.Inspector();
// load the feature with ObjectID 'oid' into the inspector
await inspector.LoadAsync(firstFeatureLayer, oid);

##Load map selection into Inspector and Change Attributes

// get the currently selected features in the map
var selectedFeatures = ArcGIS.Desktop.Mapping.MapView.Active.Map.GetSelection();
// get the first layer and its corresponding selected feature OIDs
var firstSelectionSet = selectedFeatures.First();
// create an instance of the inspector class
var inspector = new ArcGIS.Desktop.Editing.Attributes.Inspector();
// load the selected features into the inspector using a list of object IDs
await inspector.LoadAsync(firstSelectionSet.Key, firstSelectionSet.Value);
// assign the new attribute value to the field "Description"
// if more than one features are loaded, the change applies to all features
inspector["Description"] = "The new value.";
// apply the changes as an edit operation
await inspector.ApplyAsync();

##Change default edit tool for a template

Requires C# 6.0 to compile.

public Task ChangeTemplateDefaultToolAsync(ArcGIS.Desktop.Mapping.FeatureLayer flayer, string toolContentGUID,
                                     string templateName) {
    return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => {
        // retrieve the edit template form the layer by name
        var template = flayer?.GetTemplate(templateName) as ArcGIS.Desktop.Editing.Templates.EditingTemplate;
        // get the definition of the layer
        var layerDef = flayer?.GetDefinition() as ArcGIS.Core.CIM.CIMFeatureLayer;

        // proceed only if there is a template with the given name 
        // and a permanent definition that can be changed
        if (template != null && !layerDef.AutoGenerateFeatureTemplates) {
            if (template.DefaultToolID != this.ID) {
                // retrieve the CIM edit template definition
                var templateDef = template.GetDefinition();

                // assign the GUID from the tool DAML definition, for example
                // <tool id="TestConstructionTool_SampleSDKTool" categoryRefID="esri_editing_construction_polyline" ….>
                //   <tooltip heading="">Tooltip text<disabledText /></tooltip>
                //   <content guid="e58239b3-9c69-49e5-ad4d-bb2ba29ff3ea" />
                // </tool>
                // then the toolContentGUID would be "e58239b3-9c69-49e5-ad4d-bb2ba29ff3ea"
                templateDef.ToolProgID = toolContentGUID;

                // set the definition back to 
                template.SetDefinition(templateDef);
            }
        }
    });
}

Home

ProSnippets: Editing

Clone this wiki locally