Cannot call Store on a recycled row while editing.

6020
5
12-14-2011 05:41 AM
MarkFoster1
New Contributor
I am getting the following error when running the Viper Pin Tool with the method used in the video

Any Suggestions Please?

http://screencast.com/t/X2G8E1m3lNm

System.Runtime.InteropServices.COMException (0x80040958): Cannot call Store on a recycled row while editing.
at ESRI.ArcGIS.Geodatabase.IFeature.Store()
at ViperPin.ViperPinForm.SetPINValue() in C:\Users\Administrator\Downloads\47e11156-57de-4b2e-ae58-f3fa72eb0e0a\ViperPin\CSharp\ViperPinForm.cs:line 209
at ViperPin.ViperPinForm.cmdOK_Click(Object sender, EventArgs e) in C:\Users\Administrator\Downloads\47e11156-57de-4b2e-ae58-f3fa72eb0e0a\ViperPin\CSharp\ViperPinForm.cs:line 89
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


Thanks,

Mark
0 Kudos
5 Replies
MarkFoster1
New Contributor
I am using the C# version located here http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/d/00010000017z000000.ht...

// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions at http://help.arcgis.com/en/sdk/10.0/usageRestrictions.htm
// 

using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Editor;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geometry;
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ViperPin
{
  public sealed class ViperPinTool : BaseTool, IShapeConstructorTool, ISketchTool
  {
    #region COM Registration Function(s)
    [ComRegisterFunction()]
    [ComVisible(false)]
    static void RegisterFunction(Type registerType)
    {
      // Required for ArcGIS Component Category Registrar support
      ArcGISCategoryRegistration(registerType);

      //
      // TODO: Add any COM registration code here
      //
    }

    [ComUnregisterFunction()]
    [ComVisible(false)]
    static void UnregisterFunction(Type registerType)
    {
      // Required for ArcGIS Component Category Registrar support
      ArcGISCategoryUnregistration(registerType);

      //
      // TODO: Add any COM unregistration code here
      //
    }

    #region ArcGIS Component Category Registrar generated code
    /// <summary>
    /// Required method for ArcGIS Component Category registration -
    /// Do not modify the contents of this method with the code editor.
    /// </summary>
    private static void ArcGISCategoryRegistration(Type registerType)
    {
      string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
      MxCommands.Register(regKey);
    }
    /// <summary>
    /// Required method for ArcGIS Component Category unregistration -
    /// Do not modify the contents of this method with the code editor.
    /// </summary>
    private static void ArcGISCategoryUnregistration(Type registerType)
    {
      string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
      MxCommands.Unregister(regKey);
    }

    #endregion
    #endregion

    private IApplication m_application;
    private IEditor3 m_editor;
    private IEditEvents_Event m_editEvents;
    private IEditEvents5_Event m_editEvents5;
    private IEditSketch3 m_edSketch;
    private IShapeConstructor m_csc;

    private ViperPinForm m_form;

    public ViperPinTool()
    {
      base.m_category = "Developer Samples"; //localizable text
      base.m_caption = "ViperPin"; //Text in construct tools window
      base.m_message = "populate parcel pin"; //localizable text 
      base.m_toolTip = "Viper PIN tool"; //localizable text 
      base.m_name = "DeveloperSamples_ViperPin"; //unique id, non-localizable (e.g. "MyCategory_ArcMapCommand")
      try
      {
        string bitmapResourceName = GetType().Name + ".bmp";
        base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
        //base.m_cursor = new System.Windows.Forms.Cursor(GetType(), GetType().Name + ".cur");
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
      }
    }

    #region ISketchTool Members
    //pass to constructor
    public void AddPoint(IPoint point, bool Clone, bool allowUndo)
    {
      m_csc.AddPoint(point, Clone, allowUndo);
    }

    public IPoint Anchor
    {
      get { return m_csc.Anchor; }
    }

    public double AngleConstraint
    {
      get { return m_csc.AngleConstraint; }
      set { m_csc.AngleConstraint = value; }
    }

    public esriSketchConstraint Constraint
    {
      get { return m_csc.Constraint; }
      set { m_csc.Constraint = value; }
    }

    public double DistanceConstraint
    {
      get { return m_csc.DistanceConstraint; }
      set { m_csc.DistanceConstraint = value; }
    }

    public bool IsStreaming
    {
      get { return m_csc.IsStreaming; }
      set { m_csc.IsStreaming = value; }
    }

    public IPoint Location
    {
      get { return m_csc.Location; }
    }

    #endregion

    #region ITool Members
    //pass to constructor
    public override void OnMouseDown(int Button, int Shift, int X, int Y)
    {
      m_csc.OnMouseDown(Button, Shift, X, Y);
    }

    public override void OnMouseMove(int Button, int Shift, int X, int Y)
    {
      m_csc.OnMouseMove(Button, Shift, X, Y);
    }

    public override void OnMouseUp(int Button, int Shift, int X, int Y)
    {
      m_csc.OnMouseUp(Button, Shift, X, Y);
    }

    public override bool OnContextMenu(int X, int Y)
    {
      return m_csc.OnContextMenu(X, Y);
    }

    public override void OnKeyDown(int keyCode, int Shift)
    {
      m_csc.OnKeyDown(keyCode, Shift);
    }

    public override void OnKeyUp(int keyCode, int Shift)
    {
      m_csc.OnKeyUp(keyCode, Shift);
    }

    public override void Refresh(int hDC)
    {
      m_csc.Refresh(hDC);
    }

    public override int Cursor
    {
      get { return m_csc.Cursor; }
    }

    public override void OnDblClick()
    {
      if (Control.ModifierKeys == Keys.Shift)
      {
        ISketchOperation so = new SketchOperation();
        so.MenuString_2 = "Finish Sketch Part";
        so.Start(m_editor);
        m_edSketch.FinishSketchPart();
        so.Finish(null);
      }
      else
        m_edSketch.FinishSketch();
    }

    public override bool Deactivate()
    {
      //unsubscribe events
      m_editEvents.OnSketchModified -= m_editEvents_OnSketchModified;
      m_editEvents5.OnShapeConstructorChanged -= m_editEvents5_OnShapeConstructorChanged;
      m_editEvents.OnSketchFinished -= m_editEvents_OnSketchFinished;
      return base.Deactivate();
    }

    #endregion

    public override void OnCreate(object hook)
    {
      if (hook == null)
        return;
      m_application = hook as IApplication;

      //get the editor
      UID editorUid = new UID();
      editorUid.Value = "esriEditor.Editor";
      m_editor = m_application.FindExtensionByCLSID(editorUid) as IEditor3;
      m_editEvents = m_editor as IEditEvents_Event;
      m_editEvents5 = m_editor as IEditEvents5_Event;
    }

    public override bool Enabled
    {
      // Enable the tool if we are editing
      get { return (m_editor.EditState == esriEditState.esriStateEditing); }
    }

    public override void OnClick()
    {
      m_edSketch = m_editor as IEditSketch3;

      //Restrict to line constructors (for this tool)
      m_edSketch.GeometryType = esriGeometryType.esriGeometryPolyline;

      //Activate a constructor based on the current sketch geometry
      if (m_edSketch.GeometryType == esriGeometryType.esriGeometryPoint)
        m_csc = new PointConstructorClass();
      else
        m_csc = new StraightConstructorClass();
      m_csc.Initialize(m_editor);
      m_edSketch.ShapeConstructor = m_csc;
      m_csc.Activate();

      //set the current task to null
      m_editor.CurrentTask = null;

      //setup events
      m_editEvents.OnSketchModified += new IEditEvents_OnSketchModifiedEventHandler(m_editEvents_OnSketchModified);
      m_editEvents5.OnShapeConstructorChanged += new IEditEvents5_OnShapeConstructorChangedEventHandler(m_editEvents5_OnShapeConstructorChanged);
      m_editEvents.OnSketchFinished += new IEditEvents_OnSketchFinishedEventHandler(m_editEvents_OnSketchFinished);

      //Create form and pass initialization parameters
      m_form = new ViperPinForm(m_editor);

      base.OnClick();
    }

    void m_editEvents_OnSketchFinished()
    {
      //send a shift-tab to hide the construction toolbar
      //SendKeys.SendWait("+{TAB}");
      OnKeyDown(9,1);

      //Show the dialog modal
      m_form.ShowDialog();
    }

    private void m_editEvents_OnSketchModified()
    {
      m_csc.SketchModified();
    }

    private void m_editEvents5_OnShapeConstructorChanged()
    {
      //activate new constructor
      m_csc.Deactivate();
      m_csc = null;
      m_csc = m_edSketch.ShapeConstructor;
      m_csc.Activate();
    }
  }
}
0 Kudos
MarkFoster1
New Contributor
And of course here is the form

// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions at http://help.arcgis.com/en/sdk/10.0/usageRestrictions.htm
// 

using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Editor;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using System;
using System.Windows.Forms;
using Microsoft.Win32;

namespace ViperPin
{
  public partial class ViperPinForm : Form
  {
    private IEditor m_editor;
    private IPolyline m_curve;
    private IEditLayers m_editLayers;
    private IEditSketch3 m_edSketch;
    private int m_lotNum;

    public ViperPinForm(IEditor3 editor)
    {
      InitializeComponent();

      m_editor = editor;
      m_edSketch = m_editor as IEditSketch3;
      m_editLayers = m_editor as IEditLayers;

      lblEditLayer.Text = m_editLayers.CurrentLayer.Name;

      //Load field combo box with field names
      IFields pFields = m_editLayers.CurrentLayer.FeatureClass.Fields;
    for (int i=0; i < pFields.FieldCount; i++)
      {
        cmbPINField.Items.Add(pFields.get_Field(i).Name);
      }

      //get pinfield from registry
      string pinField = null;
      RegistryKey pRegKey = Registry.CurrentUser.OpenSubKey("Software\\ESRI\\ViperPin");
      if (pRegKey != null)
      {
        pinField = pRegKey.GetValue("Pinfield").ToString();
      }

      //set the combo box to the pinfield
      for (int i = 0; i < pFields.FieldCount; i++)
      {
        if (pinField == pFields.get_Field(i).Name)
        {
          cmbPINField.Text = pinField;
          break;
        }
        else
        {
          cmbPINField.Text = "None";
        }
      }

      //cmbPINField.SelectedIndex = 0;
      cmbPINField.Refresh();
      m_lotNum = 1;
      txtlot.Text = "1";

      //Set center right of form to center right of screen
      this.StartPosition = FormStartPosition.Manual;
      this.Left = 0;
      this.Top = (Screen.PrimaryScreen.Bounds.Height / 2) - (this.Height / 2);
    }

    private void cmdOK_Click(object sender, EventArgs e)
    {
      m_lotNum = int.Parse(txtlot.Text);

      //Set pin value
      SetPINValue();

      //save pinfield
      RegistryKey regKey = Registry.CurrentUser.OpenSubKey("Software",true);
      RegistryKey newKey = regKey.CreateSubKey("ESRI\\ViperPin");
      newKey.SetValue("Pinfield", cmbPINField.Text);

      this.Hide();
      
      //redraw labels
      //m_editor.Display.Invalidate(null, true, (short)esriViewDrawPhase.esriViewGraphics);

      IMxDocument mxDoc;
      mxDoc = m_editor.Parent.Document as IMxDocument;
      mxDoc.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
    }

    private void cmdCancel_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void SetPINValue()
    {
      //The Theory.
      //Select polygons that intersect the sketch.
      //Construct one polyline from the boundaries and intersect with sketch.
      //Sort resulting intersection locations (multipoint) by distance of the intersect
      // from the start of the sketch and create new ordered multipoint.
      //Loop through new ordered multipoint, select underlying parcel and calc pin.

      IFeatureLayer featLayer = m_editLayers.CurrentLayer;
      m_curve = m_edSketch.Geometry as IPolyline;

      //Search parcel polys by graphic to get feature cursor
      ISpatialFilter spatialFilter = new SpatialFilterClass();
      spatialFilter.Geometry = m_curve;
      spatialFilter.GeometryField = m_editLayers.CurrentLayer.FeatureClass.ShapeFieldName;
      spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelCrosses;

      IFeatureCursor featCursor = featLayer.Search(spatialFilter,true);
      IFeature feature = featCursor.NextFeature();

      //If we have no intersects then exit
      if (feature == null)
        return;
  
      //Make a GeomBag of the polygons boundaries (polylines)
      IGeometryCollection geomBag = new GeometryBagClass();
      object missing = Type.Missing;
      while (feature != null)
      {
        ITopologicalOperator poly = feature.Shape as ITopologicalOperator;
        geomBag.AddGeometry(poly.Boundary,ref missing,ref missing);
        feature = featCursor.NextFeature();
      }

      //Make one polyline from the boundaries
      IPolyline polyLineU = new PolylineClass();
      ITopologicalOperator topoOp = polyLineU as ITopologicalOperator;
      topoOp.ConstructUnion(geomBag as IEnumGeometry);

      //Get the intersections of the boundaries and the curve
      IPointCollection pointCol = topoOp.Intersect(m_curve, esriGeometryDimension.esriGeometry0Dimension) as IPointCollection;

      //The point collection is not ordered by distance along the curve so
      //need to create a new collection with this info

      int[] pointOrder = new int[pointCol.PointCount];
      double dac = 0, dfc = 0;
      bool bRS = false;

      for (int i = 0; i < pointCol.PointCount; i++)
      {
        IPoint queryPoint = new PointClass();
        pointCol.QueryPoint(i, queryPoint);
        m_curve.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, queryPoint, false, null,ref dac,ref dfc,ref bRS);
        pointOrder = (int)dac;
      }

      //use built in bubble sort
      System.Array.Sort(pointOrder);

      //Loop through the sorted array and calc midpoint between parcel boundaries
      IPointCollection midPoints = new MultipointClass();

      for (int i = 0; i < pointOrder.Length -1; i++)
      {
        //Get the midpoint distance
        double midPointDist = (pointOrder + pointOrder[i + 1]) / 2;
        
        //create a point at the distance and store in point collection
        IPoint queryPoint = new PointClass();
        m_curve.QueryPoint(esriSegmentExtension.esriNoExtension, midPointDist, false, queryPoint);
        midPoints.AddPoint(queryPoint,ref missing,ref missing);
      }

      //If ends of sketch are included then add them as points
      if (chkEnds.Checked)
      {
        object before = 0 as object;
        midPoints.AddPoint(m_curve.FromPoint, ref before, ref missing);
        midPoints.AddPoint(m_curve.ToPoint, ref missing, ref missing);
      }

      m_editor.StartOperation();

      //Loop through calculated midpoints, select polygon and calc pin
      for (int i = 0; i < midPoints.PointCount; i++)
      {
        IPoint midPoint = midPoints.get_Point(i);
        spatialFilter = new SpatialFilterClass();
        spatialFilter.Geometry = midPoint;
        spatialFilter.GeometryField = m_editLayers.CurrentLayer.FeatureClass.ShapeFieldName;
        spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelWithin;

        featCursor = featLayer.Search(spatialFilter, true);
        while ((feature = featCursor.NextFeature()) != null)
        {
          feature.set_Value(feature.Fields.FindField(cmbPINField.Text), m_lotNum);
          feature.Store();
          m_lotNum += int.Parse(txtlotinc.Text);
        }
      }
      m_editor.StopOperation("ViperPIN");
      txtlot.Text = m_lotNum.ToString();
    }
  }
}


0 Kudos
by Anonymous User
Not applicable
Hi Mark,

Change the following line in the SetPINValue routine in ViperPinForm.cs
from:
featCursor = featLayer.Search(spatialFilter, true);
to
featCursor = featLayer.Search(spatialFilter, false);

This will return the search cursor as a non-recycling cursor, which it should have been all along, so the returned row can be modified in an edit session.

I'll get the sample changed. What service pack do you have installed?
0 Kudos
MarkFoster1
New Contributor
Sean,

That worked perfectly. I am running ArcMap 10 with the latest service pack.

Thanks So Much,

Mark
0 Kudos
TriskaHoover
New Contributor
Hi, I'm getting this error when using the tool to Split lines at inflection points. I am using ArcMap 10.1, and attempting to convert my data in preparation for importing into the parcel fabric.

Thanks.
0 Kudos