编辑

编辑操作方法

编辑操作创建要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var createFeatures = new EditOperation();
createFeatures.Name = "Create Features";
//Create a feature with a polygon
var token = createFeatures.Create(featureLayer, polygon);
if (createFeatures.IsSucceeded)
{
// token.ObjectID wll be populated with the objectID of the created feature after Execute has been successful
}
//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();

使用当前模板创建要素

1
2
3
4
5
6
7
var myTemplate = ArcGIS.Desktop.Editing.Templates.EditingTemplate.Current;

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

从修改后的检查器创建要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var insp = new ArcGIS.Desktop.Editing.Attributes.Inspector();
insp.Load(layer, 86);

ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
// modify attributes if necessary
// insp["Field1"] = newValue;

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

从 CSV 文件创建要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//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;

// determine the shape field name - it may not be 'Shape'
string shapeField = layer.GetFeatureClass().GetDefinition().GetShapeField();

//Loop through csv data
foreach (var item in csvData)
{

//Create the point geometry
ArcGIS.Core.Geometry.MapPoint newMapPoint =
ArcGIS.Core.Geometry.MapPointBuilderEx.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(shapeField, newMapPoint);

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

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

编辑操作 使用表模板在表中创建行

1
2
3
4
5
6
var tableTemplate = standaloneTable.GetTemplates().FirstOrDefault();
var createRow = new EditOperation();
createRow.Name = "Create a row in a table";
//Creating a new row in a standalone table using the table template of your choice
createRow.Create(tableTemplate);
createRow.Execute();

编辑操作剪辑特征

1
2
3
4
5
6
7
8
9
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();

编辑操作切割要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var select = MapView.Active.SelectFeatures(clipPoly);

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

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

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

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

编辑操作删除要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var deleteFeatures = new EditOperation();
deleteFeatures.Name = "Delete Features";
var table = MapView.Active.Map.StandaloneTables[0];
//Delete a row in a standalone table
deleteFeatures.Delete(table, oid);

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

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

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

编辑操作重复要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
var duplicateFeatures = new EditOperation();
duplicateFeatures.Name = "Duplicate Features";

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

//Execute to execute the operation
//Must be called within QueuedTask.Run
var insp2 = new Inspector();
insp2.Load(featureLayer, oid);
var geom = insp2["SHAPE"] as Geometry;

var rtoken = duplicateFeatures.Create(insp2.MapMember, insp2.ToDictionary(a => a.FieldName, a => a.CurrentValue));
if (duplicateFeatures.Execute())
{
var modifyOp = duplicateFeatures.CreateChainedOperation();
modifyOp.Modify(featureLayer, (long)rtoken.ObjectID, GeometryEngine.Instance.Move(geom, 500.0, 500.0));
modifyOp.Execute();
}

}

编辑操作分解特征

1
2
3
4
5
6
7
8
9
10
11
12
13
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();

编辑操作合并功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var mergeFeatures = new EditOperation();
mergeFeatures.Name = "Merge Features";

//Merge three features into a new feature using defaults
//defined in the current template
//At 2.x -
//mergeFeatures.Merge(this.CurrentTemplate as EditingFeatureTemplate, featureLayer, new List<long>() { 10, 96, 12 });
mergeFeatures.Merge(this.CurrentTemplate as EditingRowTemplate, 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();

编辑操作 修改单个特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var modifyFeature = new EditOperation();
modifyFeature.Name = "Modify a feature";

//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)

modifyFeature.Modify(modifyInspector);

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

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

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

编辑操作 修改多个要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Search by attribute
var queryFilter = new QueryFilter();
queryFilter.WhereClause = "OBJECTID < 1000000";
//Create list of oids to update
var oidSet = new List<long>();
using (var rc = featureLayer.Search(queryFilter))
{
while (rc.MoveNext())
{
using (var record = rc.Current)
{
oidSet.Add(record.GetObjectID());
}
}
}

//create and execute the edit operation
var modifyFeatures = new EditOperation();
modifyFeatures.Name = "Modify features";
modifyFeatures.ShowProgressor = true;

var muultipleFeaturesInsp = new Inspector();
muultipleFeaturesInsp.Load(featureLayer, oidSet);
muultipleFeaturesInsp["MOMC"] = 24;
modifyFeatures.Modify(muultipleFeaturesInsp);
modifyFeatures.ExecuteAsync();

搜索图层要素并更新字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 filter = new ArcGIS.Core.Data.QueryFilter();
filter.WhereClause = "CONTRACTOR = 'KCGM'";

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

//Create edit operation
var modifyOp = new ArcGIS.Desktop.Editing.EditOperation();
modifyOp.Name = "Update date";

// load features into inspector and update field
var dateInsp = new ArcGIS.Desktop.Editing.Attributes.Inspector();
dateInsp.Load(disLayer, oids);
dateInsp["InspDate"] = "9/21/2013";

// modify and execute
modifyOp.Modify(insp);
modifyOp.Execute();
});

移动要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Get all of the selected ObjectIDs from the layer.
var firstLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
var selectionfromMap = firstLayer.GetSelection();

// set up a dictionary to store the layer and the object IDs of the selected features
var selectionDictionary = new Dictionary<MapMember, List<long>>();
selectionDictionary.Add(firstLayer as MapMember, selectionfromMap.GetObjectIDs().ToList());

var moveFeature = new EditOperation();
moveFeature.Name = "Move features";
//at 2.x - moveFeature.Move(selectionDictionary, 10, 10); //specify your units along axis to move the geometry
moveFeature.Move(SelectionSet.FromDictionary(selectionDictionary), 10, 10); //specify your units along axis to move the geometry

moveFeature.Execute();

将要素移动到特定坐标

1
2
3
4
5
6
7
8
9
10
11
//Get all of the selected ObjectIDs from the layer.
var abLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
var mySelection = abLayer.GetSelection();
var selOid = mySelection.GetObjectIDs().FirstOrDefault();

var moveToPoint = new MapPointBuilderEx(1.0, 2.0, 3.0, 4.0, MapView.Active.Map.SpatialReference); //can pass in coordinates.

var modifyFeatureCoord = new EditOperation();
modifyFeatureCoord.Name = "Move features";
modifyFeatureCoord.Modify(abLayer, selOid, moveToPoint.ToGeometry()); //Modify the feature to the new geometry
modifyFeatureCoord.Execute();

编辑操作平面化要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// note - EditOperation.Planarize requires a standard license. 
// An exception will be thrown if Pro is running under a basic license.

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();

编辑操作并行偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Create parrallel features from the selected features

//find the roads layer
var roadsLayer = MapView.Active.Map.FindLayers("Roads").FirstOrDefault();

//instatiate paralleloffset builder and set parameters
var parOffsetBuilder = new ParallelOffset.Builder()
{
Selection = MapView.Active.Map.GetSelection(),
Template = roadsLayer.GetTemplate("Freeway"),
Distance = 200,
Side = ParallelOffset.SideType.Both,
Corner = ParallelOffset.CornerType.Mitered,
Iterations = 1,
AlignConnected = false,
CopyToSeparateFeatures = false,
RemoveSelfIntersectingLoops = true
};

//create editoperation and execute
var parrallelOp = new EditOperation();
parrallelOp.Create(parOffsetBuilder);
parrallelOp.Execute();

编辑操作重塑特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var reshapeFeatures = new EditOperation();
reshapeFeatures.Name = "Reshape Features";

reshapeFeatures.Reshape(featureLayer, oid, modifyLine);

//Reshape a set of features that intersect some geometry....

//at 2.x - var selFeatures = MapView.Active.GetFeatures(modifyLine).Select(
// k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));
//reshapeFeatures.Reshape(selFeatures, modifyLine);

reshapeFeatures.Reshape(MapView.Active.GetFeatures(modifyLine), modifyLine);

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

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

编辑操作旋转要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var rotateFeatures = new EditOperation();
rotateFeatures.Name = "Rotate Features";

//Rotate works on a selected set of features
//Get all features that intersect a polygon

//at 2.x - var rotateSelection = MapView.Active.GetFeatures(polygon).Select(
// k => new KeyValuePair<MapMember, List<long>>(k.Key as MapMember, k.Value));
//rotateFeatures.Rotate(rotateSelection, origin, Math.PI / 2);

//Rotate selected features 90 deg about "origin"
rotateFeatures.Rotate(MapView.Active.GetFeatures(polygon), origin, Math.PI / 2);

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

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

编辑操作比例要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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));
//scaleFeatures.Scale(scaleSelection, origin, 2.0, 2.0, 0.0);

//Scale the selected features by 2.0 in the X and Y direction
scaleFeatures.Scale(MapView.Active.GetFeatures(polygon), 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();

编辑操作拆分要素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var splitFeatures = new EditOperation();
splitFeatures.Name = "Split Features";

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

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

// split using percentage
var splitByPercentage = new SplitByPercentage() { Percentage = 33, SplitFromStartPoint = true };
splitFeatures.Split(featureLayer, oid, splitByPercentage);

// split using equal parts
var splitByEqualParts = new SplitByEqualParts() { NumParts = 3 };
splitFeatures.Split(featureLayer, oid, splitByEqualParts);

// split using single distance
var splitByDistance = new SplitByDistance() { Distance = 27.3, SplitFromStartPoint = false };
splitFeatures.Split(featureLayer, oid, splitByDistance);

// split using varying distance
var distances = new List<double>() { 12.5, 38.2, 89.99 };
var splitByVaryingDistance = new SplitByVaryingDistance() { Distances = distances, SplitFromStartPoint = true, ProportionRemainder = true };
splitFeatures.Split(featureLayer, oid, splitByVaryingDistance);

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

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

编辑操作变换特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var transformFeatures = new EditOperation();
transformFeatures.Name = "Transform Features";

//Transform a selected set of features
//At 2.x - 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);

var affine_transform = new TransformByLinkLayer()
{
LinkLayer = linkLayer,
TransformType = TransformMethodType.Affine //TransformMethodType.Similarity
};
//Transform a selected set of features
transformFeatures.Transform(MapView.Active.GetFeatures(polygon), affine_transform);
//Perform an affine transformation
transformFeatures.Transform(featureLayer, affine_transform);

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

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

编辑操作橡皮板功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Perform rubbersheet by geometries
var rubbersheetMethod = new RubbersheetByGeometries()
{
RubbersheetType = RubbersheetMethodType.Linear, //The RubbersheetType can be Linear of NearestNeighbor
LinkLines = linkLines, //IEnumerable list of link lines (polylines)
AnchorPoints = anchorPoints, //IEnumerable list of anchor points (map points)
LimitedAdjustmentAreas = limitedAdjustmentAreas //IEnumerable list of limited adjustment areas (polygons)
};

var rubbersheetOp = new EditOperation();
//Performs linear rubbersheet transformation on the features belonging to "layer" that fall within the limited adjustment areas
rubbersheetOp.Rubbersheet(layer, rubbersheetMethod);
//Execute the operation
rubbersheetOp.Execute();

//Alternatively, you can also perform rubbersheet by layer
var rubbersheetMethod2 = new RubbersheetByLayers()
{
RubbersheetType = RubbersheetMethodType.NearestNeighbor, //The RubbersheetType can be Linear of NearestNeighbor
LinkLayer = linkLayer,
AnchorPointLayer = anchorPointsLayer,
LimitedAdjustmentAreaLayer = limitedAdjustmentAreaLayer
};

//Performs nearest neighbor rubbersheet transformation on the features belonging to "layer" that fall within the limited adjustment areas
rubbersheetOp.Rubbersheet(layer, rubbersheetMethod2);
//Execute the operation
rubbersheetOp.Execute();

编辑操作 执行剪辑、剪切和平坦化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//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.Split(featureLayer, oid, cutLine);
clipCutPlanarizeFeatures.Planarize(featureLayer, 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();

编辑操作链 编辑操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//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
var token2 = editOperation1.Create(this.CurrentTemplate, polygon);
if (editOperation1.IsSucceeded)
{
newFeatureID = (long)token2.ObjectID;
}
//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();

编辑操作通过行令牌添加附件

1
2
3
4
5
6
7
8
9
10
11
//ArcGIS Pro 2.5 extends the EditOperation.AddAttachment method to take a RowToken as a paramter.
//This allows you to create a feature, using EditOperation.CreateEx, and add an attachment in one transaction.

var editOpAttach = new EditOperation();
editOperation1.Name = string.Format("Create point in '{0}'", CurrentTemplate.Layer.Name);

var attachRowToken = editOpAttach.Create(this.CurrentTemplate, polygon);
editOpAttach.AddAttachment(attachRowToken, @"c:\temp\image.jpg");

//Must be within a QueuedTask
editOpAttach.Execute();

SetOnUndone, SetOnRedone, SetOnComitted

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// SetOnUndone, SetOnRedone and SetOnComittedManage can be used to manage 
// external actions(such as writing to a log table) that are associated with
// each edit operation.

//get selected feature and update attribute
var selectedFeatures = MapView.Active.Map.GetSelection();
var testInspector = new Inspector();
testInspector.Load(selectedFeatures.ToDictionary().Keys.First(), selectedFeatures.ToDictionary().Values.First());
testInspector["Name"] = "test";

//create and execute the edit operation
var updateTestField = new EditOperation();
updateTestField.Name = "Update test field";
updateTestField.Modify(insp);

//actions for SetOn...
updateTestField.SetOnUndone(() =>
{
//Sets an action that will be called when this operation is undone.
Debug.WriteLine("Operation is undone");
});

updateTestField.SetOnRedone(() =>
{
//Sets an action that will be called when this editoperation is redone.
Debug.WriteLine("Operation is redone");
});

updateTestField.SetOnComitted((bool b) => //called on edit session save(true)/discard(false).
{
// Sets an action that will be called when this editoperation is committed.
Debug.WriteLine("Operation is committed");
});

updateTestField.Execute();
}

启用编辑

启用编辑

1
2
3
4
5
6
7
8
9
10
11
12
// if not editing
if (!Project.Current.IsEditingEnabled)
{
var res = MessageBox.Show("You must enable editing to use editing tools. Would you like to enable editing?",
"Enable Editing?", System.Windows.MessageBoxButton.YesNoCancel);
if (res == System.Windows.MessageBoxResult.No ||
res == System.Windows.MessageBoxResult.Cancel)
{
return;
}
Project.Current.SetIsEditingEnabledAsync(true);
}

禁用编辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// if editing
if (Project.Current.IsEditingEnabled)
{
var res = MessageBox.Show("Do you want to disable editing? Editing tools will be disabled",
"Disable Editing?", System.Windows.MessageBoxButton.YesNoCancel);
if (res == System.Windows.MessageBoxResult.No ||
res == System.Windows.MessageBoxResult.Cancel)
{
return;
}

//we must check for edits
if (Project.Current.HasEdits)
{
res = MessageBox.Show("Save edits?", "Save Edits?", System.Windows.MessageBoxButton.YesNoCancel);
if (res == System.Windows.MessageBoxResult.Cancel)
return;
else if (res == System.Windows.MessageBoxResult.No)
Project.Current.DiscardEditsAsync();
else
{
Project.Current.SaveEditsAsync();
}
}
Project.Current.SetIsEditingEnabledAsync(false);
}

地图拓扑

构建地图拓扑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private async Task BuildGraphWithActiveView()
{
await QueuedTask.Run(() =>
{
//Build the map topology graph
MapView.Active.BuildMapTopologyGraph<TopologyDefinition>(async topologyGraph =>
{
//Getting the nodes and edges present in the graph
var topologyGraphNodes = topologyGraph.GetNodes();
var topologyGraphEdges = topologyGraph.GetEdges();

foreach (var node in topologyGraphNodes)
{
// do something with the node
}
foreach (var edge in topologyGraphEdges)
{
// do something with the edge
}

MessageBox.Show($"Number of topo graph nodes are: {topologyGraphNodes.Count}.\n Number of topo graph edges are {topologyGraphEdges.Count}.", "Map Topology Info");
});
});
}

行事件

订阅行事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
protected void SubscribeRowEvent()
{
QueuedTask.Run(() =>
{
//Listen for row events on a layer
var featLayer = MapView.Active.GetSelectedLayers().First() as FeatureLayer;
var layerTable = featLayer.GetTable();

//subscribe to row events
var rowCreateToken = RowCreatedEvent.Subscribe(OnRowCreated, layerTable);
var rowChangeToken = RowChangedEvent.Subscribe(OnRowChanged, layerTable);
var rowDeleteToken = RowDeletedEvent.Subscribe(OnRowDeleted, layerTable);
});
}

protected void OnRowCreated(RowChangedEventArgs args)
{
}

protected void OnRowChanged(RowChangedEventArgs args)
{
}

protected void OnRowDeleted(RowChangedEventArgs args)
{
}

在行事件中的映射中的单独表中创建记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Use the EditOperation in the RowChangedEventArgs to append actions to be executed. 
// Your actions will become part of the operation and combined into one item on the undo stack

private void HookRowCreatedEvent()
{
// subscribe to the RowCreatedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowCreatedEvent.Subscribe(MyRowCreatedEvent, table);
}

private void MyRowCreatedEvent(RowChangedEventArgs args)
{
// RowEvent callbacks are always called on the QueuedTask so there is no need
// to wrap your code within a QueuedTask.Run lambda.

// get the edit operation
var parentEditOp = args.Operation;

// set up some attributes
var attribs = new Dictionary<string, object> { };
attribs.Add("Layer", "Parcels");
attribs.Add("Description", "OID: " + args.Row.GetObjectID().ToString() + " " + DateTime.Now.ToShortTimeString());

//create a record in an audit table
var sTable = MapView.Active.Map.FindStandaloneTables("EditHistory").First();
var table = sTable.GetTable();
parentEditOp.Create(table, attribs);
}

在行事件中的单独表中创建记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Use the EditOperation in the RowChangedEventArgs to append actions to be executed. 
// Your actions will become part of the operation and combined into one item on the undo stack

private void HookCreatedEvent()
{
// subscribe to the RowCreatedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowCreatedEvent.Subscribe(OnRowCreatedEvent, table);
}

private void OnRowCreatedEvent(RowChangedEventArgs args)
{
// RowEvent callbacks are always called on the QueuedTask so there is no need
// to wrap your code within a QueuedTask.Run lambda.

// update a separate table not in the map when a row is created
// You MUST use the ArcGIS.Core.Data API to edit the table. Do NOT
// use a new edit operation in the RowEvent callbacks
try
{
// get the edit operation
var parentEditOp = args.Operation;

// set up some attributes
var attribs = new Dictionary<string, object> { };
attribs.Add("Description", "OID: " + args.Row.GetObjectID().ToString() + " " + DateTime.Now.ToShortTimeString());

// update Notes table with information about the new feature
using (var geoDatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
{
using (var table = geoDatabase.OpenDataset<Table>("Notes"))
{
parentEditOp.Create(table, attribs);
}
}
}
catch (Exception e)
{
MessageBox.Show($@"Error in OnRowCreated for OID: {args.Row.GetObjectID()} : {e.ToString()}");
}
}

修改行事件中的记录 - 使用 Row.Store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private void HookRowChangedEvent()
{
// subscribe to the RowChangedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowChangedEvent.Subscribe(OnRowChangedEvent, table);
}

private Guid _currentRowChangedGuid = Guid.Empty;
protected void OnRowChangedEvent(RowChangedEventArgs args)
{
// RowEvent callbacks are always called on the QueuedTask so there is no need
// to wrap your code within a QueuedTask.Run lambda.

var row = args.Row;

// check for re-entry (only if row.Store is called)
if (_currentRowChangedGuid == args.Guid)
return;

var fldIdx = row.FindField("POLICE_DISTRICT");
if (fldIdx != -1)
{
//Validate any change to �police district�
// cancel the edit if validation on the field fails
if (row.HasValueChanged(fldIdx))
{
// cancel edit with invalid district (5)
var value = row["POLICE_DISTRICT"].ToString();
if (value == "5")
{
//Cancel edits with invalid �police district� values
args.CancelEdit($"Police district {row["POLICE_DISTRICT"]} is invalid");
}
}

// update the description field
row["Description"] = "Row Changed";

// this update with cause another OnRowChanged event to occur
// keep track of the row guid to avoid recursion
_currentRowChangedGuid = args.Guid;
row.Store();
_currentRowChangedGuid = Guid.Empty;
}
}

修改行事件中的记录 - 使用 EditOperation.Modify

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void HookChangedEvent()
{
// subscribe to the RowChangedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowChangedEvent.Subscribe(MyRowChangedEvent, table);
}

private void MyRowChangedEvent(RowChangedEventArgs args)
{
// RowEvent callbacks are always called on the QueuedTask so there is no need
// to wrap your code within a QueuedTask.Run lambda.

//example of modifying a field on a row that has been created
var parentEditOp = args.Operation;

// avoid recursion
if (_lastEdit != args.Guid)
{
//update field on change
parentEditOp.Modify(args.Row, "ZONING", "New");

_lastEdit = args.Guid;
}
}

确定编辑时几何图形是否更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private static FeatureLayer featureLayer;
private static void DetermineGeometryChange()
{
featureLayer = MapView.Active?.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
if (featureLayer == null)
return;

QueuedTask.Run(() =>
{
//Listen to the RowChangedEvent that occurs when a Row is changed.
ArcGIS.Desktop.Editing.Events.RowChangedEvent.Subscribe(OnRowChangedEvent2, featureLayer.GetTable());
});
}
private static void OnRowChangedEvent2(RowChangedEventArgs args)
{
// RowEvent callbacks are always called on the QueuedTask so there is no need
// to wrap your code within a QueuedTask.Run lambda.

//Get the layer's definition
var lyrDefn = featureLayer.GetFeatureClass().GetDefinition();
//Get the shape field of the feature class
string shapeField = lyrDefn.GetShapeField();
//Index of the shape field
var shapeIndex = lyrDefn.FindField(shapeField);
//Original geometry of the modified row
var geomOrig = args.Row.GetOriginalValue(shapeIndex) as Geometry;
//New geometry of the modified row
var geomNew = args.Row[shapeIndex] as Geometry;
//Compare the two
bool shapeChanged = geomOrig.IsEqual(geomNew);
}

取消删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static void StopADelete()
{
// subscribe to the RowDeletedEvent for the appropriate table
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowDeletedEvent.Subscribe(OnRowDeletedEvent, table);
}

private static void OnRowDeletedEvent(RowChangedEventArgs args)
{
// RowEvent callbacks are always called on the QueuedTask so there is no need
// to wrap your code within a QueuedTask.Run lambda.

var row = args.Row;

// cancel the delete if the feature is in Police District 5

var fldIdx = row.FindField("POLICE_DISTRICT");
if (fldIdx != -1)
{
var value = row[fldIdx].ToString();
if (value == "5")
{
//cancel with dialog
// Note - feature edits on Hosted and Standard Feature Services cannot be cancelled.
args.CancelEdit("Delete Event\nAre you sure", true);

// or cancel without a dialog
// args.CancelEdit();
}
}
}

编辑已完成事件

订阅编辑已完成事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void subEditEvents()
{
//subscribe to editcompleted
var eceToken = EditCompletedEvent.Subscribe(onEce);
}

protected Task onEce(EditCompletedEventArgs args)
{
//show number of edits
Console.WriteLine("Creates: " + args.Creates.ToDictionary().Values.Sum(list => list.Count).ToString());
Console.WriteLine("Modifies: " + args.Modifies.ToDictionary().Values.Sum(list => list.Count).ToString());
Console.WriteLine("Deletes: " + args.Deletes.ToDictionary().Values.Sum(list => list.Count).ToString());
return Task.FromResult(0);
}

检查员

将要素从图层加载到检查器中

1
2
3
4
5
6
7
8
// 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);

将地图选择加载到检查器中

1
2
3
4
5
6
7
8
9
// 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.ToDictionary().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);

获取所选要素的属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
QueuedTask.Run(() =>
{

// 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.ToDictionary().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
inspector.Load(firstSelectionSet.Key, firstSelectionSet.Value);

//get the value of
var pscode = inspector["STATE_NAME"];
var myGeometry = inspector.Shape;
});

将地图选择加载到检查器并更改属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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.ToDictionary().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 - but with no undo/redo
await inspector.ApplyAsync();

使用检查器获取图层方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
QueuedTask.Run(() =>
{
var firstFeatureLayer = 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 layer
inspector.LoadSchema(firstFeatureLayer);

// iterate through the attributes, looking at properties
foreach (var attribute in inspector)
{
var fldName = attribute.FieldName;
var fldAlias = attribute.FieldAlias;
var fldType = attribute.FieldType;
int idxFld = attribute.FieldIndex;
var fld = attribute.GetField();
var isNullable = attribute.IsNullable;
var isEditable = attribute.IsEditable;
var isVisible = attribute.IsVisible;
var isSystemField = attribute.IsSystemField;
var isGeometryField = attribute.IsGeometryField;
}
});

检查器.添加验证

1
2
3
4
5
6
7
8
9
10
var insp = new Inspector();
insp.LoadSchema(featLayer);
var attrib = insp.Where(a => a.FieldName == "Mineral").First();

attrib.AddValidate(() =>
{
if (attrib.CurrentValue.ToString() == "Salt")
return Enumerable.Empty<ArcGIS.Desktop.Editing.Attributes.Attribute.ValidationError>();
else return new[] { ArcGIS.Desktop.Editing.Attributes.Attribute.ValidationError.Create("Error", ArcGIS.Desktop.Editing.Attributes.Severity.Low) };
});

访问 Blob 字段

使用属性检查器读取和写入 Blob 字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
QueuedTask.Run(() =>
{
//get selected feature into inspector
var selectedFeatures = MapView.Active.Map.GetSelection();

var insp = new Inspector();
insp.Load(selectedFeatures.ToDictionary().Keys.First(), selectedFeatures.ToDictionary().Values.First());

//read a blob field and save to a file
var msw = new MemoryStream();
msw = insp["Blobfield"] as MemoryStream;
using (FileStream file = new FileStream(@"d:\temp\blob.jpg", FileMode.Create, FileAccess.Write))
{
msw.WriteTo(file);
}

//read file into memory stream
var msr = new MemoryStream();
using (FileStream file = new FileStream(@"d:\images\Hydrant.jpg", FileMode.Open, FileAccess.Read))
{
file.CopyTo(msr);
}

//put the memory stream in the blob field and save to feature
var op = new EditOperation();
op.Name = "Blob Inspector";
insp["Blobfield"] = msr;
op.Modify(insp);
op.Execute();
});

在回调中使用行游标读取和写入 Blob 字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
QueuedTask.Run(() =>
{
var editOp = new EditOperation();
editOp.Name = "Blob Cursor";
var featLayer = MapView.Active.Map.FindLayers("Hydrant").First() as FeatureLayer;

editOp.Callback((context) =>
{
using (var rc = featLayer.GetTable().Search(null, false))
{
while (rc.MoveNext())
{
using (var record = rc.Current)
{
//read the blob field and save to a file
var msw = new MemoryStream();
msw = record["BlobField"] as MemoryStream;
using (FileStream file = new FileStream(@"d:\temp\blob.jpg", FileMode.Create, FileAccess.Write))
{
msw.WriteTo(file);
}

//read file into memory stream
var msr = new MemoryStream();
using (FileStream file = new FileStream(@"d:\images\Hydrant.jpg", FileMode.Open, FileAccess.Read))
{
file.CopyTo(msr);
}

//put the memory stream in the blob field and save to feature
record["BlobField"] = msr;
record.Store();

}
}
}
}, featLayer.GetTable());
editOp.Execute();
});

访问栅格字段

从栅格字段读取

1
2
3
4
5
6
7
8
9
10
QueuedTask.Run(() =>
{
var sel = MapView.Active.Map.GetSelection();

//Read a raster from a raster field as an InteropBitmap
//the bitmap can then be used as an imagesource or written to disk
var insp = new ArcGIS.Desktop.Editing.Attributes.Inspector();
insp.Load(sel.ToDictionary().Keys.First(), sel.ToDictionary().Values.First());
var ibmp = insp["Photo"] as System.Windows.Interop.InteropBitmap;
});

将图像写入栅格字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
QueuedTask.Run(() =>
{
var sel = MapView.Active.Map.GetSelection();

//Insert an image into a raster field
//Image will be written with no compression
var insp = new ArcGIS.Desktop.Editing.Attributes.Inspector();
insp.Load(sel.ToDictionary().Keys.First(), sel.ToDictionary().Values.First());
insp["Photo"] = @"e:\temp\Hydrant.jpg";

var op = new EditOperation();
op.Name = "Raster Inspector";
op.Modify(insp);
op.Execute();
});

将压缩图像写入栅格字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
QueuedTask.Run(() =>
{
//Open the raster dataset on disk and create a compressed raster value dataset object
var dataStore = new ArcGIS.Core.Data.FileSystemDatastore(new ArcGIS.Core.Data.FileSystemConnectionPath(new System.Uri(@"e:\temp"), ArcGIS.Core.Data.FileSystemDatastoreType.Raster));
using (var fileRasterDataset = dataStore.OpenDataset<ArcGIS.Core.Data.Raster.RasterDataset>("Hydrant.jpg"))
{
var storageDef = new ArcGIS.Core.Data.Raster.RasterStorageDef();
storageDef.SetCompressionType(ArcGIS.Core.Data.Raster.RasterCompressionType.JPEG);
storageDef.SetCompressionQuality(90);

var rv = new ArcGIS.Core.Data.Raster.RasterValue();
rv.SetRasterDataset(fileRasterDataset);
rv.SetRasterStorageDef(storageDef);

var sel = MapView.Active.Map.GetSelection();

//insert a raster value object into the raster field
var insp = new ArcGIS.Desktop.Editing.Attributes.Inspector();
insp.Load(sel.ToDictionary().Keys.First(), sel.ToDictionary().Values.First());
insp["Photo"] = rv;

var op = new EditOperation();
op.Name = "Raster Inspector";
op.Modify(insp);
op.Execute();
}
});

使用草图

切换草图选择模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//UseSelection = true; (UseSelection must be set to true in the tool constructor or tool activate)
private bool _inSelMode = false;

public bool IsShiftKey(MapViewKeyEventArgs k)
{
return (k.Key == System.Windows.Input.Key.LeftShift ||
k.Key == System.Windows.Input.Key.RightShift);
}

protected override async void OnToolKeyDown(MapViewKeyEventArgs k)
{
//toggle sketch selection mode with a custom key
if (k.Key == System.Windows.Input.Key.W)
{
if (!_inSelMode)
{
k.Handled = true;

// Toggle the tool to select mode.
// The sketch is saved if UseSelection = true;
if (await ActivateSelectAsync(true))
_inSelMode = true;
}
}
else if (!_inSelMode)
{
//disable effect of Shift in the base class.
//Mark the key event as handled to prevent further processing
k.Handled = IsShiftKey(k);
}
}
protected override void OnToolKeyUp(MapViewKeyEventArgs k)
{
if (k.Key == System.Windows.Input.Key.W)
{
if (_inSelMode)
{
_inSelMode = false;
k.Handled = true;//process this one

// Toggle back to sketch mode. If UseSelection = true
// the sketch will be restored
ActivateSelectAsync(false);
}
}
else if (_inSelMode)
{
//disable effect of Shift in the base class.
//Mark the key event as handled to prevent further processing
k.Handled = IsShiftKey(k);
}
}

聆听草图修改事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// SketchModified event is fired by 
// - COTS construction tools (except annotation, dimension geometry types),
// - Edit Vertices, Reshape, Align Features
// - 3rd party tools with FireSketchEvents = true


//Subscribe the sketch modified event
//ArcGIS.Desktop.Mapping.Events.SketchModifiedEvent.Subscribe(OnSketchModified);

private void OnSketchModified(ArcGIS.Desktop.Mapping.Events.SketchModifiedEventArgs args)
{
// if not an undo operation
if (!args.IsUndo)
{
// what was the sketch before the change?
var prevSketch = args.PreviousSketch;
// what is the current sketch?
var currentSketch = args.CurrentSketch;
if (currentSketch is Polyline polyline)
{
// Examine the current (last) vertex in the line sketch
var lastSketchPoint = polyline.Points.Last();

// do something with the last point
}
}
}

收听草图完成前事件并修改草图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// BeforeSketchCompleted event is fired by 
// - COTS construction tools (except annotation, dimension geometry types),
// - Edit Vertices, Reshape, Align Features
// - 3rd party tools with FireSketchEvents = true


//Subscribe to the before sketch completed event
//ArcGIS.Desktop.Mapping.Events.BeforeSketchCompletedEvent.Subscribe(OnBeforeSketchCompleted);

private Task OnBeforeSketchCompleted(BeforeSketchCompletedEventArgs args)
{
//assign sketch Z values from default surface and set the sketch geometry
var modifiedSketch = args.MapView.Map.GetZsFromSurfaceAsync(args.Sketch).Result;
args.SetSketchGeometry(modifiedSketch.Geometry);
return Task.CompletedTask;
}

收听草图完成事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SketchCompleted event is fired by 
// - COTS construction tools (except annotation, dimension geometry types),
// - Edit Vertices, Reshape, Align Features
// - 3rd party tools with FireSketchEvents = true


//Subscribe to the sketch completed event
//ArcGIS.Desktop.Mapping.Events.SketchCompletedEvent.Subscribe(OnSketchCompleted);

private void OnSketchCompleted(SketchCompletedEventArgs args)
{
// get the sketch
var finalSketch = args.Sketch;

// do something with the sketch - audit trail perhaps
}

触发草图事件的自定义构造工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
internal class ConstructionTool1 : MapTool
{
public ConstructionTool1()
{
IsSketchTool = true;
UseSnapping = true;
// Select the type of construction tool you wish to implement.
// Make sure that the tool is correctly registered with the correct component category type in the daml
SketchType = SketchGeometryType.Line;
//Gets or sets whether the sketch is for creating a feature and should use the CurrentTemplate.
UsesCurrentTemplate = true;

// set FireSketchEvents property to true
FireSketchEvents = true;
}

// ...
}

自定义自定义草图工具的草图符号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//Custom tools have the ability to change the symbology used when sketching a new feature. 
//Both the Sketch Segment Symbol and the Vertex Symbol can be modified using the correct set method.
//This is set in the activate method for the tool.
protected override Task OnToolActivateAsync(bool active)
{
QueuedTask.Run(() =>
{
//Getting the current symbology options of the segment
var segmentOptions = GetSketchSegmentSymbolOptions();
//Modifying the primary and secondary color and the width of the segment symbology options
var deepPurple = new CIMRGBColor();
deepPurple.R = 75;
deepPurple.G = 0;
deepPurple.B = 110;
segmentOptions.PrimaryColor = deepPurple;
segmentOptions.Width = 4;
segmentOptions.HasSecondaryColor = true;
var pink = new CIMRGBColor();
pink.R = 219;
pink.G = 48;
pink.B = 130;
segmentOptions.SecondaryColor = pink;
//Creating a new vertex symbol options instance with the values you want
var vertexOptions = new VertexSymbolOptions(VertexSymbolType.RegularUnselected);
var yellow = new CIMRGBColor();
yellow.R = 255;
yellow.G = 215;
yellow.B = 0;
var purple = new CIMRGBColor();
purple.R = 148;
purple.G = 0;
purple.B = 211;
vertexOptions.AngleRotation = 45;
vertexOptions.Color = yellow;
vertexOptions.MarkerType = VertexMarkerType.Star;
vertexOptions.OutlineColor = purple;
vertexOptions.OutlineWidth = 3;
vertexOptions.Size = 5;

//Setting the value of the segment symbol options
SetSketchSegmentSymbolOptions(segmentOptions);
//Setting the value of the vertex symbol options of the regular unselected vertices using the vertexOptions instance created above.
SetSketchVertexSymbolOptions(VertexSymbolType.RegularUnselected, vertexOptions);
});

return base.OnToolActivateAsync(active);
}

捕捉

配置捕捉 - 打开或关闭捕捉

1
2
3
4
5
//enable snapping
ArcGIS.Desktop.Mapping.Snapping.IsEnabled = true;

// disable snapping
ArcGIS.Desktop.Mapping.Snapping.IsEnabled = false;

配置捕捉 - 应用程序捕捉模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// set only Point and Edge snapping modes, clear everything else
//At 2.x - ArcGIS.Desktop.Mapping.Snapping.SetSnapModes(SnapMode.Point, SnapMode.Edge);
ArcGIS.Desktop.Mapping.Snapping.SetSnapModes(
new List<SnapMode>() { SnapMode.Point, SnapMode.Edge });

// clear all snap modes
//At 2.x - ArcGIS.Desktop.Mapping.Snapping.SetSnapModes();
ArcGIS.Desktop.Mapping.Snapping.SetSnapModes(null);


// set snap modes one at a time
ArcGIS.Desktop.Mapping.Snapping.SetSnapMode(SnapMode.Edge, true);
ArcGIS.Desktop.Mapping.Snapping.SetSnapMode(SnapMode.End, true);
ArcGIS.Desktop.Mapping.Snapping.SetSnapMode(SnapMode.Intersection, true);

// get current snap modes
var snapModes = ArcGIS.Desktop.Mapping.Snapping.SnapModes;

// get state of a specific snap mode
bool isOn = ArcGIS.Desktop.Mapping.Snapping.GetSnapMode(SnapMode.Vertex);

配置捕捉 - 图层捕捉可捕捉性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// is the layer snappable?
bool isSnappable = fLayer.IsSnappable;

// set snappability for a specific layer - needs to run on the MCT
await QueuedTask.Run(() =>
{
// use an extension method
fLayer.SetSnappable(true);

// or use the CIM directly
//var layerDef = fLayer.GetDefinition() as ArcGIS.Core.CIM.CIMGeoFeatureLayerBase;
//layerDef.Snappable = true;
//fLayer.SetDefinition(layerDef);
});


// turn all layers snappability off
layerList = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>();
await QueuedTask.Run(() =>
{
foreach (var layer in layerList)
{
layer.SetSnappable(false);
}
});

配置捕捉 - 图层捕捉模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
layerList = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>();

// configure by layer
foreach (var layer in layerList)
{
// find the state of the snapModes for the layer
var lsm = ArcGIS.Desktop.Mapping.Snapping.GetLayerSnapModes(layer);
bool vertexOn = lsm.Vertex;
// or use
vertexOn = lsm.GetSnapMode(SnapMode.Vertex);

bool edgeOn = lsm.Edge;
// or use
edgeOn = lsm.GetSnapMode(SnapMode.Edge);

bool endOn = lsm.End;
// or use
endOn = lsm.GetSnapMode(SnapMode.End);

// update a few snapModes
// turn Vertex off
lsm.SetSnapMode(SnapMode.Vertex, false);
// intersections on
lsm.SetSnapMode(SnapMode.Intersection, true);

// and set back to the layer
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(layer, lsm);


// assign a single snap mode at once
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(layer, SnapMode.Vertex, false);


// turn ALL snapModes on
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(layer, true);
// turn ALL snapModes off
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(layer, false);
}


// configure for a set of layers

// set Vertex, edge, end on for a set of layers, other snapModes false
var vee = new LayerSnapModes(false);
vee.Vertex = true;
vee.Edge = true;
vee.End = true;
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(layerList, vee);


// ensure intersection is on for a set of layers without changing any other snapModes

// get the layer snapModes for the set of layers
var dictLSM = ArcGIS.Desktop.Mapping.Snapping.GetLayerSnapModes(layerList);
foreach (var layer in dictLSM.Keys)
{
var lsm = dictLSM[layer];
lsm.Intersection = true;
}
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(dictLSM);


// set all snapModes off for a list of layers
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(layerList, false);

配置捕捉 - 组合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// interested in only snapping to the vertices of a specific layer of interest and not the vertices of other layers
// all other snapModes should be off.

// snapping must be on
ArcGIS.Desktop.Mapping.Snapping.IsEnabled = true;

// turn all application snapModes off
//At 2.x - ArcGIS.Desktop.Mapping.Snapping.SetSnapModes();
ArcGIS.Desktop.Mapping.Snapping.SetSnapModes(null);

// set application snapMode vertex on
ArcGIS.Desktop.Mapping.Snapping.SetSnapMode(SnapMode.Vertex, true);

// ensure layer snapping is on
await QueuedTask.Run(() =>
{
fLayer.SetSnappable(true);
});

// set vertex snapping only
var vertexOnly = new LayerSnapModes(false);
vertexOnly.Vertex = true;

// set vertex only for the specific layer, clearing all others
var dict = new Dictionary<Layer, LayerSnapModes>();
dict.Add(fLayer, vertexOnly);
ArcGIS.Desktop.Mapping.Snapping.SetLayerSnapModes(dict, true); // true = reset other layers

捕捉选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Set snapping options via get/set options
var snapOptions = ArcGIS.Desktop.Mapping.Snapping.GetOptions(myMap);
//At 2.x - snapOptions.SnapToSketchEnabled = true;
snapOptions.IsSnapToSketchEnabled = true;
snapOptions.XYTolerance = 100;
//At 2.x - snapOptions.ZToleranceEnabled = true;
snapOptions.IsZToleranceEnabled = true;
snapOptions.ZTolerance = 0.6;

//turn on snap tip display parts
snapOptions.SnapTipDisplayParts = (int)SnapTipDisplayPart.SnapTipDisplayLayer + (int)SnapTipDisplayPart.SnapTipDisplayType;

//turn off all snaptips
//snapOptions.SnapTipDisplayParts = (int)SnapTipDisplayPart.SnapTipDisplayNone;

//turn on layer display only
//snapOptions.SnapTipDisplayParts = (int)SnapTipDisplayPart.SnapTipDisplayLayer;

//At 2.x - snapOptions.GeometricFeedbackColor = ColorFactory.Instance.RedRGB;
snapOptions.SnapTipColor = ColorFactory.Instance.RedRGB;

ArcGIS.Desktop.Mapping.Snapping.SetOptions(myMap, snapOptions);

撤消/重做

撤消/重做最近的操作

1
2
3
4
5
6
7
//undo
if (MapView.Active.Map.OperationManager.CanUndo)
MapView.Active.Map.OperationManager.UndoAsync();//await as needed

//redo
if (MapView.Active.Map.OperationManager.CanRedo)
MapView.Active.Map.OperationManager.RedoAsync();//await as needed

编辑模板

在图层上按名称查找编辑模板

1
2
3
4
5
6
7
8
9
10
ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
//get the templates
var map = ArcGIS.Desktop.Mapping.MapView.Active.Map;
if (map == null)
return;

var mainTemplate = map.FindLayers("main").FirstOrDefault()?.GetTemplate("Distribution");
var mhTemplate = map.FindLayers("Manhole").FirstOrDefault()?.GetTemplate("Active");
});

查找属于独立表的表模板

1
2
3
4
5
6
7
8
9
10
11
ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
var map = ArcGIS.Desktop.Mapping.MapView.Active.Map;
if (map == null)
return;
//Get a particular table template
var tableTemplate = map.FindStandaloneTables("Address Points").FirstOrDefault()?.GetTemplate("Residences");
//Get all the templates of a standalone table
var ownersTableTemplates = map.FindStandaloneTables("Owners").FirstOrDefault()?.GetTemplates();
var statisticsTableTemplates = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().First(l => l.Name.Equals("Trading Statistics")).GetTemplates();
});

当前模板

1
EditingTemplate template = EditingTemplate.Current;

更改模板的默认编辑工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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;
if ((template == null) || (layerDef == null))
return;

if (template.DefaultToolID != this.ID)
{
bool updateLayerDef = false;
if (layerDef.AutoGenerateFeatureTemplates)
{
layerDef.AutoGenerateFeatureTemplates = false;
updateLayerDef = true;
}

// 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"

//At 2.x -
//templateDef.ToolProgID = toolContentGUID;
templateDef.DefaultToolGUID = toolContentGUID;

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

// update the layer definition too
if (updateLayerDef)
flayer.SetDefinition(layerDef);
}
});
}

隐藏或显示模板上的编辑工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
QueuedTask.Run(() =>
{
//hide all tools except line tool on layer
var featLayer = MapView.Active.Map.FindLayers("Roads").First();

var editTemplates = featLayer.GetTemplates();
var newCIMEditingTemplates = new List<CIMEditingTemplate>();

foreach (var et in editTemplates)
{
//initialize template by activating default tool
et.ActivateDefaultToolAsync();
var cimEditTemplate = et.GetDefinition();
//get the visible tools on this template
var allTools = et.ToolIDs.ToList();
//add the hidden tools on this template
allTools.AddRange(cimEditTemplate.GetExcludedToolIDs().ToList());
//hide all the tools then allow the line tool

//At 2.x -
//allTools.AddRange(cimEditTemplate.GetExcludedToolDamlIds().ToList());
allTools.AddRange(cimEditTemplate.GetExcludedToolIDs().ToList());

//At 2.x -
//cimEditTemplate.SetExcludedToolDamlIds(allTools.ToArray());
//cimEditTemplate.AllowToolDamlID("esri_editing_SketchLineTool");

cimEditTemplate.SetExcludedToolIDs(allTools.ToArray());
cimEditTemplate.AllowToolID("esri_editing_SketchLineTool");
newCIMEditingTemplates.Add(cimEditTemplate);
}
//update the layer templates
var layerDef = featLayer.GetDefinition() as CIMFeatureLayer;
// Set AutoGenerateFeatureTemplates to false for template changes to stick
layerDef.AutoGenerateFeatureTemplates = false;
layerDef.FeatureTemplates = newCIMEditingTemplates.ToArray();
featLayer.SetDefinition(layerDef);
});

使用图层创建新模板。创建模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var layer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
if (layer == null)
return;
QueuedTask.Run(() =>
{
var insp = new Inspector();
insp.LoadSchema(layer);

insp["Field1"] = value1;
insp["Field2"] = value2;
insp["Field3"] = value3;

var tags = new[] { "Polygon", "tag1", "tag2" };

// set defaultTool using a daml-id
string defaultTool = "esri_editing_SketchCirclePolygonTool";

// tool filter is the tools to filter OUT
var toolFilter = new[] { "esri_editing_SketchTracePolygonTool" };

// create a new template
var newTemplate = layer.CreateTemplate("My new template", "description", insp, defaultTool, tags, toolFilter);
});

使用表创建新表模板。创建模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var table = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().FirstOrDefault();
if (table == null)
return;
QueuedTask.Run(() =>
{
var tableTemplate = table.GetTemplate("Template1");

var definition = tableTemplate.GetDefinition();
definition.Description = "New definition";
definition.Name = "New name";
//Create new table template using this definition
table.CreateTemplate(definition);

//You can also create a new table template using this extension method. You can use this method the same way you use the layer.CreateTemplate method.
table.CreateTemplate("New template name", "Template description", tags: new string[] { "tag 1", "tag 2" });
});

更新表模板

1
2
3
4
5
6
7
8
9
10
QueuedTask.Run(() =>
{
var tableTemplate = table.GetTemplate("Template1");

var definition = tableTemplate.GetDefinition();
definition.Description = "New definition";
definition.Name = "New name";
// update the definition
tableTemplate.SetDefinition(definition);
});

创建注释模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// get an anno layer
AnnotationLayer annoLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<AnnotationLayer>().FirstOrDefault();
if (annoLayer == null)
return;

QueuedTask.Run(() =>
{
Inspector insp = null;
// get the anno feature class
var fc = annoLayer.GetFeatureClass() as ArcGIS.Core.Data.Mapping.AnnotationFeatureClass;

// get the featureclass CIM definition which contains the labels, symbols
var cimDefinition = fc.GetDefinition() as ArcGIS.Core.Data.Mapping.AnnotationFeatureClassDefinition;
var labels = cimDefinition.GetLabelClassCollection();
var symbols = cimDefinition.GetSymbolCollection();

// make sure there are labels, symbols
if ((labels.Count == 0) || (symbols.Count == 0))
return;

// find the label class required
// typically you would use a subtype name or some other characteristic
// in this case lets just use the first one

var label = labels[0];

// each label has a textSymbol
// the symbolName *should* be the symbolID to be used
var symbolName = label.TextSymbol.SymbolName;
int symbolID = -1;
if (!int.TryParse(symbolName, out symbolID))
{
// int.TryParse fails - attempt to find the symbolName in the symbol collection
foreach (var symbol in symbols)
{
if (symbol.Name == symbolName)
{
symbolID = symbol.ID;
break;
}
}
}
// no symbol?
if (symbolID == -1)
return;

// load the schema
insp = new Inspector();
insp.LoadSchema(annoLayer);

// ok to assign these fields using the inspector[fieldName] methodology
// these fields are guaranteed to exist in the annotation schema
insp["AnnotationClassID"] = label.ID;
insp["SymbolID"] = symbolID;

// set up some additional annotation properties
AnnotationProperties annoProperties = insp.GetAnnotationProperties();
annoProperties.FontSize = 36;
annoProperties.TextString = "My Annotation feature";
annoProperties.VerticalAlignment = VerticalAlignment.Top;
annoProperties.HorizontalAlignment = HorizontalAlignment.Justify;

insp.SetAnnotationProperties(annoProperties);

var tags = new[] { "Annotation", "tag1", "tag2" };

// use daml-id rather than guid
string defaultTool = "esri_editing_SketchStraightAnnoTool";

// tool filter is the tools to filter OUT
var toolFilter = new[] { "esri_editing_SketchCurvedAnnoTool" };

// create a new template
var newTemplate = annoLayer.CreateTemplate("new anno template", "description", insp, defaultTool, tags, toolFilter);
});

删除表模板

1
2
3
4
5
6
7
8
9
10
11
var table = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().FirstOrDefault();
if (table == null)
return;
QueuedTask.Run(() =>
{
var tableTemplate = table.GetTemplate("Template1");
//Removing a table template
table.RemoveTemplate(tableTemplate);
//Removing a template by name
table.RemoveTemplate("Template2");
});

活动模板已更改

1
2
3
4
5
6
7
8
9
10
11
12
ArcGIS.Desktop.Editing.Events.ActiveTemplateChangedEvent.Subscribe(OnActiveTemplateChanged);

async void OnActiveTemplateChanged(ArcGIS.Desktop.Editing.Events.ActiveTemplateChangedEventArgs args)
{
// return if incoming template is null
if (args.IncomingTemplate == null)
return;

// Activate two-point line tool for Freeway template in the Layers map
if (args.IncomingTemplate.Name == "Freeway" && args.IncomingMapView.Map.Name == "Layers")
await args.IncomingTemplate.ActivateToolAsync("esri_editing_SketchTwoPointLineTool");
}

注解

注释构建工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//In your config.daml...set the categoryRefID
//<tool id="..." categoryRefID="esri_editing_construction_annotation" caption="Create Anno" ...>

//Sketch type Point or Line or BezierLine in the constructor...
//internal class AnnoConstructionTool : MapTool {
// public AnnoConstructionTool() {
// IsSketchTool = true;
// UseSnapping = true;
// SketchType = SketchGeometryType.Point;
//

protected async override Task<bool> OnSketchCompleteAsync(Geometry geometry)
{
if (CurrentTemplate == null || geometry == null)
return false;

// Create an edit operation
var createOperation = new EditOperation();
createOperation.Name = string.Format("Create {0}", CurrentTemplate.Layer.Name);
createOperation.SelectNewFeatures = true;

var insp = CurrentTemplate.Inspector;
var result = await QueuedTask.Run(() =>
{
// get the annotation properties class
AnnotationProperties annoProperties = insp.GetAnnotationProperties();
// set custom annotation properties
annoProperties.TextString = "my custom text";
annoProperties.Color = ColorFactory.Instance.RedRGB;
annoProperties.FontSize = 24;
annoProperties.FontName = "Arial";
annoProperties.HorizontalAlignment = ArcGIS.Core.CIM.HorizontalAlignment.Right;
annoProperties.Shape = geometry;
// assign annotation properties back to the inspector
insp.SetAnnotationProperties(annoProperties);

// Queue feature creation
createOperation.Create(CurrentTemplate.Layer, insp);

// Execute the operation
return createOperation.Execute();
});
return result;
}

以编程方式启动编辑批注

1
2
3
var plugin = FrameworkApplication.GetPlugInWrapper("esri_editing_EditVerticesText");
if (plugin.Enabled)
((ICommand)plugin).Execute(null);

更新批注文本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
await QueuedTask.Run(() =>
{
//annoLayer is ~your~ Annotation layer...

// use the inspector methodology
//at 2.x - var insp = new Inspector(true);
var insp = new Inspector();
insp.Load(annoLayer, oid);

// get the annotation properties
AnnotationProperties annoProperties = insp.GetAnnotationProperties();
// set the attribute
annoProperties.TextString = "Hello World";
// assign the annotation proeprties back to the inspector
insp.SetAnnotationProperties(annoProperties);

//create and execute the edit operation
EditOperation op = new EditOperation();
op.Name = "Update annotation";
op.Modify(insp);
op.Execute();
});

修改批注形状

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
await QueuedTask.Run(() =>
{
//Don't use 'Shape'....Shape is the bounding box of the annotation text. This is NOT what you want...
//
//var insp = new Inspector();
//insp.Load(annoLayer, oid);
//var shape = insp["SHAPE"] as Polygon;
//...wrong shape...

//Instead, we must use the AnnotationProperties

//annoLayer is ~your~ Annotation layer
//at 2.x - var insp = new Inspector(true);
var insp = new Inspector();
insp.Load(annoLayer, oid);

AnnotationProperties annoProperties = insp.GetAnnotationProperties();
var shape = annoProperties.Shape;
if (shape.GeometryType != GeometryType.GeometryBag)
{
var newGeometry = GeometryEngine.Instance.Move(shape, 10, 10);
annoProperties.Shape = newGeometry;
insp.SetAnnotationProperties(annoProperties);

EditOperation op = new EditOperation();
op.Name = "Change annotation angle";
op.Modify(insp);
op.Execute();
}
});

修改批注文本图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
await QueuedTask.Run(() =>
{

var selection = annoLayer.GetSelection();
if (selection.GetCount() == 0)
return;

// use the first selelcted feature
//at 2.x - var insp = new Inspector(true);
var insp = new Inspector();
insp.Load(annoLayer, selection.GetObjectIDs().FirstOrDefault());

// getAnnoProperties should return null if not an annotation feature
AnnotationProperties annoProperties = insp.GetAnnotationProperties();
// get the textGraphic
CIMTextGraphic textGraphic = annoProperties.TextGraphic;

// change text
textGraphic.Text = "Hello world";

// set x,y offset via the symbol
var symbol = textGraphic.Symbol.Symbol;
var textSymbol = symbol as CIMTextSymbol;
textSymbol.OffsetX = 2;
textSymbol.OffsetY = 3;

textSymbol.HorizontalAlignment = HorizontalAlignment.Center;

// load the updated textGraphic
annoProperties.LoadFromTextGraphic(textGraphic);
// assign the annotation properties back
insp.SetAnnotationProperties(annoProperties);

EditOperation op = new EditOperation();
op.Name = "modify symbol";
op.Modify(insp);
bool result = op.Execute();
});

ProSnippet 组 : 接地到网格

G2G 设置

1
2
3
4
5
6
7
8
CIMGroundToGridCorrection correction = null;
bool isCorecting = correction.IsCorrecting(); // equivalent to correction != null && correction.Enabled;
bool UsingOffset = correction.UsingDirectionOffset(); // equivalent to correction.IsCorrecting() && correction.UseDirection;
double dOffset = correction.GetDirectionOffset(); // equivalent to correction.UsingDirectionOffset() ? correction.Direction : DefaultDirectionOffset;
bool usingDistanceFactor = correction.UsingDistanceFactor(); // equivalent to correction.IsCorrecting() && correction.UseScale;
bool usingElevation = correction.UsingElevationMode(); // equivalent to correction.UsingDistanceFactor() && c.ScaleType == GroundToGridScaleType.ComputeUsingElevation;
bool usingSFactor = correction.UsingConstantScaleFactor(); //; equivalent to correction.UsingDistanceFactor() && correction.ScaleType == GroundToGridScaleType.ConstantFactor;
double dSFactor = correction.GetConstantScaleFactor(); // equivalent to correctionc.UsingDistanceFactor() ? correction.ConstantScaleFactor : DefaultConstantScaleFactor;

编辑选项

获取/设置编辑选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//toggle, switch option values
var options = ApplicationOptions.EditingOptions;

options.EnforceAttributeValidation = !options.EnforceAttributeValidation;
options.WarnOnSubtypeChange = !options.WarnOnSubtypeChange;
options.InitializeDefaultValuesOnSubtypeChange = !options.InitializeDefaultValuesOnSubtypeChange;
options.UncommitedAttributeEdits = (options.UncommitedAttributeEdits ==
UncommitedEditMode.AlwaysPrompt) ? UncommitedEditMode.Apply : UncommitedEditMode.AlwaysPrompt;

options.StretchGeometry = !options.StretchGeometry;
options.StretchTopology = !options.StretchTopology;
options.UncommitedGeometryEdits = (options.UncommitedGeometryEdits ==
UncommitedEditMode.AlwaysPrompt) ? UncommitedEditMode.Apply : UncommitedEditMode.AlwaysPrompt;

options.ActivateMoveAfterPaste = !options.ActivateMoveAfterPaste;
options.ShowFeatureSketchSymbology = !options.ShowFeatureSketchSymbology;
options.FinishSketchOnDoubleClick = !options.FinishSketchOnDoubleClick;
options.AllowVertexEditingWhileSketching = !options.AllowVertexEditingWhileSketching;
options.ShowDeleteDialog = !options.ShowDeleteDialog;
options.EnableStereoEscape = !options.EnableStereoEscape;
options.DragSketch = !options.DragSketch;
options.ShowDynamicConstraints = !options.ShowDynamicConstraints;
options.IsDeflectionDefaultDirectionConstraint =
!options.IsDeflectionDefaultDirectionConstraint;
options.IsDirectionDefaultInputConstraint = !options.IsDirectionDefaultInputConstraint;
options.ShowEditingToolbar = !options.ShowEditingToolbar;
options.ToolbarPosition = (options.ToolbarPosition == ToolbarPosition.Bottom) ?
ToolbarPosition.Right : ToolbarPosition.Bottom;
options.ToolbarSize = (options.ToolbarSize == ToolbarSize.Medium) ?
ToolbarSize.Small : ToolbarSize.Medium;
options.MagnifyToolbar = !options.MagnifyToolbar;

options.EnableEditingFromEditTab = !options.EnableEditingFromEditTab;
options.AutomaticallySaveEdits = !options.AutomaticallySaveEdits;
options.AutoSaveByTime = !options.AutoSaveByTime;
options.SaveEditsInterval = (options.AutomaticallySaveEdits) ? 20 : 10;
options.SaveEditsOperations = (options.AutomaticallySaveEdits) ? 60 : 30;
options.SaveEditsOnProjectSave = !options.SaveEditsOnProjectSave;
options.ShowSaveEditsDialog = !options.ShowSaveEditsDialog;
options.ShowDiscardEditsDialog = !options.ShowDiscardEditsDialog;
options.DeactivateToolOnSaveOrDiscard = !options.DeactivateToolOnSaveOrDiscard;
options.NewLayersEditable = !options.NewLayersEditable;

获取草图折点符号系统选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var options = ApplicationOptions.EditingOptions;

//Must use QueuedTask
QueuedTask.Run(() =>
{
//There are 4 vertex symbol settings - selected, unselected and the
//current vertex selected and unselected.
var reg_select = options.GetVertexSymbolOptions(VertexSymbolType.RegularSelected);
var reg_unsel = options.GetVertexSymbolOptions(VertexSymbolType.RegularUnselected);
var curr_sel = options.GetVertexSymbolOptions(VertexSymbolType.CurrentSelected);
var curr_unsel = options.GetVertexSymbolOptions(VertexSymbolType.CurrentUnselected);

//to convert the options to a symbol use
//GetPointSymbol
var reg_sel_pt_symbol = reg_select.GetPointSymbol();
//ditto for reg_unsel, curr_sel, curr_unsel
});

获取草图线段符号系统选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//var options = ApplicationOptions.EditingOptions;
QueuedTask.Run(() =>
{
var seg_options = options.GetSegmentSymbolOptions();
//to convert the options to a symbol use
//SymbolFactory. Note: this is approximate....sketch isn't using the
//CIM directly for segments
var layers = new List<CIMSymbolLayer>();
var stroke0 = SymbolFactory.Instance.ConstructStroke(seg_options.PrimaryColor,
seg_options.Width, SimpleLineStyle.Dash);
layers.Add(stroke0);
if (seg_options.HasSecondaryColor) {
var stroke1 = SymbolFactory.Instance.ConstructStroke(
seg_options.SecondaryColor, seg_options.Width, SimpleLineStyle.Solid);
layers.Add(stroke1);
}
//segment symbology only
var sketch_line = new CIMLineSymbol() {
SymbolLayers = layers.ToArray()
};
});

设置草图顶点符号选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//var options = ApplicationOptions.EditingOptions;
QueuedTask.Run(() =>
{
//change the regular unselected vertex symbol
//default is a green, hollow, square, 5pts. Change to
//Blue outline diamond, 10 pts
var vertexSymbol = new VertexSymbolOptions(VertexSymbolType.RegularUnselected);
vertexSymbol.OutlineColor = ColorFactory.Instance.BlueRGB;
vertexSymbol.MarkerType = VertexMarkerType.Diamond;
vertexSymbol.Size = 10;

//Are these valid?
if (options.CanSetVertexSymbolOptions(
VertexSymbolType.RegularUnselected, vertexSymbol)) {
//apply them
options.SetVertexSymbolOptions(VertexSymbolType.RegularUnselected, vertexSymbol);
}
});

设置草图线段符号选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//var options = ApplicationOptions.EditingOptions;
QueuedTask.Run(() =>
{
//change the segment symbol primary color to green and
//width to 1 pt
var segSymbol = options.GetSegmentSymbolOptions();
segSymbol.PrimaryColor = ColorFactory.Instance.GreenRGB;
segSymbol.Width = 1;

//Are these valid?
if (options.CanSetSegmentSymbolOptions(segSymbol)) {
//apply them
options.SetSegmentSymbolOptions(segSymbol);
}
});

将草图顶点符号设置回默认值

1
2
3
4
5
6
7
8
9
10
//var options = ApplicationOptions.EditingOptions;
QueuedTask.Run(() =>
{
//ditto for reg selected and current selected, unselected
var def_reg_unsel =
options.GetDefaultVertexSymbolOptions(VertexSymbolType.RegularUnselected);
//apply default
options.SetVertexSymbolOptions(
VertexSymbolType.RegularUnselected, def_reg_unsel);
});

将草图线段符号设置回默认值

1
2
3
4
5
6
//var options = ApplicationOptions.EditingOptions;
QueuedTask.Run(() =>
{
var def_seg = options.GetDefaultSegmentSymbolOptions();
options.SetSegmentSymbolOptions(def_seg);
});

版本控制选项

获取和设置版本控制选项

1
2
3
4
5
6
7
8
9
var vOptions = ApplicationOptions.VersioningOptions;

vOptions.DefineConflicts = (vOptions.DefineConflicts == ConflictDetectionType.ByRow) ?
ConflictDetectionType.ByColumn : ConflictDetectionType.ByRow;
vOptions.ConflictResolution = (
vOptions.ConflictResolution == ConflictResolutionType.FavorEditVersion) ?
ConflictResolutionType.FavorTargetVersion : ConflictResolutionType.FavorEditVersion;
vOptions.ShowConflictsDialog = !vOptions.ShowConflictsDialog;
vOptions.ShowReconcileDialog = !vOptions.ShowReconcileDialog;

创建注记构造工具

通过属性更新批注文本。警告:TEXTSTRING Anno 属性必须存在

旋转或移动批注

更改批注文本图形

公共设施网络

创建公共设施网络关联

在单个编辑操作中创建公共设施网络要素和关联

tion)