//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;//protectedasyncoverrideTask<bool>OnSketchCompleteAsync(Geometrygeometry){if(CurrentTemplate==null||geometry==null)returnfalse;// Create an edit operationvarcreateOperation=new EditOperation();
createOperation.Name =string.Format("Create {0}", CurrentTemplate.Layer.Name);
createOperation.SelectNewFeatures =true;// update the geometry point into a 2 point line//annotation needs at minimum a 2 point line for the text to be placeddoubletol=0.01;varpolyline=await CreatePolylineFromPointAsync((MapPoint)geometry, tol);// Queue feature creation
createOperation.Create(CurrentTemplate, polyline);// Execute the operationreturnawait createOperation.ExecuteAsync();}internalTask<Polyline>CreatePolylineFromPointAsync(MapPointpt,doubletolerance){return QueuedTask.Run(()=>{// create a polyline from a starting point//use a tolerance to construct the second pointMapPointpt2= MapPointBuilder.CreateMapPoint(pt.X +tolerance, pt.Y, pt.SpatialReference);return PolylineBuilder.CreatePolyline(newList<MapPoint>(){ pt, pt2 });});}
Update Annotation Text via attribute. Caveat: The TEXTSTRING Anno attribute must exist
//See "Change Annotation Text Graphic" for an alternative if TEXTSTRING is missing from the schemaawait QueuedTask.Run(()=>{//annoLayer is ~your~ Annotation layer...// use the inspector methodologyvarinsp=new Inspector(); insp.Load(annoLayer, oid);// make sure TextString attribute exists.//It is not guaranteed to be in the schema ArcGIS.Desktop.Editing.Attributes.Attribute att= insp.FirstOrDefault(a => a.FieldName =="TEXTSTRING");if(att!=null){ insp["TEXTSTRING"]="Hello World";//create and execute the edit operationEditOperationop=new EditOperation(); op.Name ="Update annotation"; op.Modify(insp);//OR using a Dictionary - again TEXTSTRING has to exist in the schema//Dictionary<string, object> newAtts = new Dictionary<string, object>();//newAtts.Add("TEXTSTRING", "hello world");//op.Modify(annoLayer, oid, newAtts); op.Execute();}});
Rotate or Move the Annotation
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 get the TextGraphic from the anno feature.//The TextGraphic shape will be the anno baseline...//At 2.1 the only way to retrieve this textLine is to obtain the TextGraphic from the AnnotationFeatureQueryFilterqf=new QueryFilter(){WhereClause="OBJECTID = 1"};//annoLayer is ~your~ Annotation layerusing(varrowCursor= annoLayer.Search(qf)){if(rowCursor.MoveNext()){using(varannoFeature= rowCursor.Current as ArcGIS.Core.Data.Mapping.AnnotationFeature){vargraphic= annoFeature.GetGraphic();vartextGraphic= graphic as CIMTextGraphic;vartextLine= textGraphic.Shape as Polyline;// rotate the shape 90 degreesvarorigin= GeometryEngine.Instance.Centroid(textLine);GeometryrotatedPolyline= GeometryEngine.Instance.Rotate(textLine, origin, System.Math.PI /2);//Move the line 5 "units" in the x and y direction//GeometryEngine.Instance.Move(textLine, 5, 5);EditOperationop=new EditOperation(); op.Name ="Change annotation angle"; op.Modify(annoLayer, oid, rotatedPolyline); op.Execute();}}}});
Get the Annotation Text Graphic
await QueuedTask.Run(()=>{varrc= annoLayer.GetTable().Search(); rc.MoveNext();varaf= rc.Current as AnnotationFeature;vargraphic= af.GetGraphic();vartextGraphic= graphic as CIMTextGraphic;//Note: //var outline_geom = af.GetGraphicOutline(); //gets the anno text outline geometry... af.Dispose(); rc.Dispose();});
Change Annotation Text Graphic
await QueuedTask.Run(()=>{EditOperationop=new EditOperation(); op.Name ="Change annotation graphic";//At 2.1 we must use an edit operation Callback... op.Callback(context =>{QueryFilterqf=new QueryFilter(){WhereClause="OBJECTID = 1"};//Cursor must be non-recycling. Use the table ~not~ the layer..i.e. "GetTable().Search()"//annoLayer is ~your~ Annotation layerusing(varrowCursor= annoLayer.GetTable().Search(qf,false)){if(rowCursor.MoveNext()){using(varannoFeature= rowCursor.Current as ArcGIS.Core.Data.Mapping.AnnotationFeature){//Get the graphic from the anno featurevargraphic= annoFeature.GetGraphic();vartextGraphic= graphic as CIMTextGraphic;// change the text and the color textGraphic.Text ="hello world";varsymbol= textGraphic.Symbol.Symbol; symbol.SetColor(ColorFactory.Instance.RedRGB); textGraphic.Symbol = symbol.MakeSymbolReference();// update the graphic annoFeature.SetGraphic(textGraphic);// store is required annoFeature.Store();//refresh layer cache context.Invalidate(annoFeature);}}}}, annoLayer.GetTable()); op.Execute();});
Get the Outline Geometry for an Annotation
varannoLayer= MapView.Active.Map.GetLayersAsFlattenedList().OfType<AnnotationLayer>().FirstOrDefault();if(annoLayer==null)return;
QueuedTask.Run(()=>{//get the first annotation feature...//...assuming at least one feature gets selectedvarrc= annoLayer.GetFeatureClass().Search(); rc.MoveNext();varaf= rc.Current as AnnotationFeature;varoutline_geom= af.GetGraphicOutline();//TODO - use the outline...//Note: //var graphic = annoFeature.GetGraphic(); //gets the CIMTextGraphic... af.Dispose(); rc.Dispose();});
Get the Mask Geometry for an Annotation
varannoLayer= MapView.Active.Map.GetLayersAsFlattenedList().OfType<AnnotationLayer>().FirstOrDefault();if(annoLayer==null)return;varmv= MapView.Active;
QueuedTask.Run(()=>{//get the first annotation feature...//...assuming at least one feature gets selectedvarrc= annoLayer.GetFeatureClass().Search(); rc.MoveNext();varoid= rc.Current.GetObjectID();//Use DrawingOutlineType.BoundingEnvelope to retrieve a generalized//mask geometry or "Box". The mask will be in the same SpatRef as the map.//The mask will be constructed using the anno class reference scalevarmask_geom= annoLayer.QueryDrawingOutline(oid, mv, DrawingOutlineType.Exact); rc.Dispose();});