I am using the .intersects method with my polygon to find all polygons of another type that intersect my polygon. I then use that row cursor to get a list of OIDs for the polygons that intersect that original polygon. I realize I can load all the OIDs into one inspector all at once, but they need to be updated individually.
My question is, because I need to update those intersecting polygons individually, do I need to loop through those OIDs and load them into their own inspector one by one in order to use the Inspector functionality? Will this be inefficient? In ArcObjects I simply worked with a list of features, but it seems like the inspectors are the way to go now. I am just wondering if loading every OID into there own inspector is the best practice.
Good question. Using the inspector/modify combo is the preferred method when available.
Rather than giving each row its own inspector you can reuse the same one within the modify loop:
QueuedTask.Run(() =>
{
//get selected feature geometry
var selectedFeatures = MapView.Active.Map.GetSelection();
var insp = new Inspector();
var op = new EditOperation();
op.Name = "Calc fields";
op.ShowProgressor = true;
op.ProgressMessage = "test";
//load each feature into insp and calc field
foreach (var kvp in selectedFeatures)
{
foreach (var oid in kvp.Value)
{
insp.Load(kvp.Key, oid);
insp["Date"] = DateTime.Now.ToString();
op.Modify(insp);
}
}
op.Execute();
});
There is an overhead however using the inspector vs rowcursors in a callback.
Consider the two methods to calculate a bunch of records:
inspector/modify
QueuedTask.Run(() =>
{
var sw = Stopwatch.StartNew();
//Search by attribute
var queryFilter = new QueryFilter();
queryFilter.WhereClause = "OBJECTID < 1000000";
var rc = featLayer.Search(queryFilter);
//Create list of oids to update
var oidSet = new List<long>();
while (rc.MoveNext()) { oidSet.Add(rc.Current.GetObjectID()); }
//create and execute the edit operation
var op = new EditOperation();
op.Name = "Update via inspector";
op.ShowProgressor = true;
var insp = new Inspector();
insp.Load(featLayer, oidSet);
insp["MOMC"] = 24;
op.Modify(insp);
op.ExecuteAsync();
sw.Stop();
var ExecutionTimeTaken = string.Format("Minutes :{0}\nSeconds :{1}", sw.Elapsed.Minutes, sw.Elapsed.Seconds);
ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(ExecutionTimeTaken);
});
vs a rowcursor
QueuedTask.Run(() =>
{
var sw = Stopwatch.StartNew();
var queryFilter = new QueryFilter();
queryFilter.WhereClause = "OBJECTID < 1000000";
var editOperation = new EditOperation();
editOperation.Callback(context =>
{
using (var rowCursor = featLayer.GetTable().Search(queryFilter, false))
{
while (rowCursor.MoveNext())
{
using (var feature = (Feature)rowCursor.Current)
{
feature["MOMC"] = "42";
feature.Store();
//nb: could also use row here for non-shape fields instead of feature.
}
}
}
}, featLayer.GetTable());
editOperation.ExecuteAsync();
sw.Stop();
var ExecutionTimeTaken = string.Format("Minutes :{0}\nSeconds :{1}", sw.Elapsed.Minutes, sw.Elapsed.Seconds);
ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(ExecutionTimeTaken);
});
For a million records rowcursor is faster by a minute (3 minutes vs 2)
for 100000, its a few seconds, so for most cases stick with inspector (14 seconds vs 12)
Thank You. These intersecting polygons need to redraw themselves to be fully contained within the parent polygon and must update their area values with that new confined shape. I do this through the onRowChangeEvent. My intersecting fields know how to redraw or update themselves.
So I think my best option might be to get the feature list and .store() them all. This will trigger the onRowChangeEvents for each intersecting field. In the onRowChange event, it will get the Row, and in my code I tell that Row to Confine() itself and UpdateAreas() itself.
I will test this out and let everyone know my results.