Select to view content in your preferred language

Undo just the last edit on featurelayer graphic?

830
2
Jump to solution
09-05-2012 02:35 AM
NjålEkern
New Contributor
Hi,

I am looking for a way to undo edit on a graphic.
I am trying UndoEdits (Graphic) described here: UndoEdits.html but this undoes all unsaved graphics changes on the graphic, and not just the last one.
As an example:
1. I draw a new polygon A of 4 vertices
2. I draw a new polygon B of 4 vertices
3. I change polygon A to have 5 vertices

Now, if I click a button that I have coded to perform 'myfeaturelayer.UndoEdits(polygonA)', what happens is polygon A disappears.
(Polygon B is still there).
What happened is that UndoEdits(polygonA) reverted all changes on polygonA, including it's creation. As the documentation of the API said it would.
What I would like, is to get polygon A back to its previous condition, of having 4 vertices.

Is it possible to do that?

We are using Silverlight API 2.4

Njål
0 Kudos
1 Solution

Accepted Solutions
JustinCornell
Occasional Contributor
We do just what you are talking about, however, we had to write our own.  You can listen to the EditGeomety event and check when the Action == EditCompleted and just keep track of your own graphics.  Below is a rough example of what we ended up doing.  There is a class and two extension methods we us to clone graphics.  We just push and pop the graphics sets off the stack for undo/redo.

public static ESRI.ArcGIS.Client.Graphic CloneGraphic(this ESRI.ArcGIS.Client.Graphic g) {     ESRI.ArcGIS.Client.Graphic newGraphic = new ESRI.ArcGIS.Client.Graphic()     {         MapTip = g.MapTip,         Symbol = g.Symbol,         TimeExtent = g.TimeExtent,         Selected = g.Selected,         Geometry = g.Geometry.CloneGeometry()     };      g.Attributes.CopyTo(newGraphic.Attributes);      return newGraphic; }  public static Geometry CloneGeometry(this Geometry g) {     Geometry newGeometry = null;      if (g is ESRI.ArcGIS.Client.Geometry.Envelope)     {         var env = g as Envelope;         newGeometry = new Envelope()         {             SpatialReference = env.SpatialReference,             XMax = env.XMax,             YMax = env.YMax,             XMin = env.XMin,             YMin = env.YMin,         };     }     else if (g is ESRI.ArcGIS.Client.Geometry.MapPoint)     {         var point = g as MapPoint;         newGeometry = new MapPoint(point.X, point.Y, point.SpatialReference);     }     else if (g is ESRI.ArcGIS.Client.Geometry.MultiPoint)     {         var mpoint = g as MultiPoint;         var pc = new PointCollection();         foreach (var p in mpoint.Points)             pc.Add(new MapPoint(p.X, p.Y, p.SpatialReference));          newGeometry = new MultiPoint(pc, mpoint.SpatialReference);     }     else if (g is ESRI.ArcGIS.Client.Geometry.Polygon)     {         var poly = g as Polygon;         var newPoly = new Polygon() { SpatialReference = poly.SpatialReference };         foreach (var ring in poly.Rings)         {             var pc = new PointCollection();             foreach (var p in ring)                 pc.Add(new MapPoint(p.X, p.Y, p.SpatialReference));              newPoly.Rings.Add(pc);         }          newGeometry = newPoly;     }     else if (g is ESRI.ArcGIS.Client.Geometry.Polyline)     {         var line = g as Polyline;         var newline = new Polyline() { SpatialReference = line.SpatialReference };          foreach (var path in line.Paths)         {             var pc = new PointCollection();             foreach (var p in path)                 pc.Add(new MapPoint(p.X, p.Y, p.SpatialReference));              newline.Paths.Add(pc);         }          newGeometry = newline;     }      return newGeometry; }  public class EditSnapshot {     public EditSnapshot()     {         Graphics = new List<Graphic>();     }     public EditSnapshot(Graphic g)         : this()     {         Graphics.Add(g);     }      public EditSnapshot(IEnumerable<Graphic> graphics)         : this()     {         Graphics.AddRange(graphics);     }     public List<Graphic> Graphics { get; set; } }    //Here is the actual code that we use.  Pretty simple. internal protected Stack<EditSnapshot> Snapshots { get; set; }  private void EditGeometry_GeometryEdit(object sender, EditGeometry.GeometryEditEventArgs e) {     if (e.Action == EditGeometry.Action.EditCompleted)             Snapshots.Push(new EditSnapshot(_editLayer.Graphics.Select(x => x.CloneGraphic()))); }

View solution in original post

0 Kudos
2 Replies
JustinCornell
Occasional Contributor
We do just what you are talking about, however, we had to write our own.  You can listen to the EditGeomety event and check when the Action == EditCompleted and just keep track of your own graphics.  Below is a rough example of what we ended up doing.  There is a class and two extension methods we us to clone graphics.  We just push and pop the graphics sets off the stack for undo/redo.

public static ESRI.ArcGIS.Client.Graphic CloneGraphic(this ESRI.ArcGIS.Client.Graphic g) {     ESRI.ArcGIS.Client.Graphic newGraphic = new ESRI.ArcGIS.Client.Graphic()     {         MapTip = g.MapTip,         Symbol = g.Symbol,         TimeExtent = g.TimeExtent,         Selected = g.Selected,         Geometry = g.Geometry.CloneGeometry()     };      g.Attributes.CopyTo(newGraphic.Attributes);      return newGraphic; }  public static Geometry CloneGeometry(this Geometry g) {     Geometry newGeometry = null;      if (g is ESRI.ArcGIS.Client.Geometry.Envelope)     {         var env = g as Envelope;         newGeometry = new Envelope()         {             SpatialReference = env.SpatialReference,             XMax = env.XMax,             YMax = env.YMax,             XMin = env.XMin,             YMin = env.YMin,         };     }     else if (g is ESRI.ArcGIS.Client.Geometry.MapPoint)     {         var point = g as MapPoint;         newGeometry = new MapPoint(point.X, point.Y, point.SpatialReference);     }     else if (g is ESRI.ArcGIS.Client.Geometry.MultiPoint)     {         var mpoint = g as MultiPoint;         var pc = new PointCollection();         foreach (var p in mpoint.Points)             pc.Add(new MapPoint(p.X, p.Y, p.SpatialReference));          newGeometry = new MultiPoint(pc, mpoint.SpatialReference);     }     else if (g is ESRI.ArcGIS.Client.Geometry.Polygon)     {         var poly = g as Polygon;         var newPoly = new Polygon() { SpatialReference = poly.SpatialReference };         foreach (var ring in poly.Rings)         {             var pc = new PointCollection();             foreach (var p in ring)                 pc.Add(new MapPoint(p.X, p.Y, p.SpatialReference));              newPoly.Rings.Add(pc);         }          newGeometry = newPoly;     }     else if (g is ESRI.ArcGIS.Client.Geometry.Polyline)     {         var line = g as Polyline;         var newline = new Polyline() { SpatialReference = line.SpatialReference };          foreach (var path in line.Paths)         {             var pc = new PointCollection();             foreach (var p in path)                 pc.Add(new MapPoint(p.X, p.Y, p.SpatialReference));              newline.Paths.Add(pc);         }          newGeometry = newline;     }      return newGeometry; }  public class EditSnapshot {     public EditSnapshot()     {         Graphics = new List<Graphic>();     }     public EditSnapshot(Graphic g)         : this()     {         Graphics.Add(g);     }      public EditSnapshot(IEnumerable<Graphic> graphics)         : this()     {         Graphics.AddRange(graphics);     }     public List<Graphic> Graphics { get; set; } }    //Here is the actual code that we use.  Pretty simple. internal protected Stack<EditSnapshot> Snapshots { get; set; }  private void EditGeometry_GeometryEdit(object sender, EditGeometry.GeometryEditEventArgs e) {     if (e.Action == EditGeometry.Action.EditCompleted)             Snapshots.Push(new EditSnapshot(_editLayer.Graphics.Select(x => x.CloneGraphic()))); }
0 Kudos
NjålEkern
New Contributor
Thank you very much for your answer Justin.
I will try it out, and come back to this.
Marking it as answer, it seems it will do as I want.
Regards, Njål
0 Kudos