Hello 🙂
I have a WPF window and I created a "Draw" button. This button minimize the wpf window and I would like to be able to draw some points on simple click, draw the polygon based on points on double click, then set the polygon to a row of the attributes table (in my feature layer) and maximize the wpf window.
I instantiate a "class Draw : MapTool" when I click on the "Draw" button, and try to draw some points on a graphic layer based on an example I found, but it doesn't work (and I don't want to let a graphic layer in my content). I know how to get/set the attributes table but the "draw" functions is the real problem. Is there an other way to do that please ?
Thank you ! 🙂
Solved! Go to Solution.
The attached project performs your workflow using a dockpane (not a WPF window). The project works on 2.7 or newer.
I coded your sample snippet in the code below and also found a bug in my attached solution.
First be bug: The ICommand property in the viewmodel was not named properly it should have been named:
/// <summary>
/// hook existing ArcGIS Pro Tool Button
/// </summary>
public ICommand CmdCreatePolygon => FrameworkApplication.GetPlugInWrapper("CreatePolygon_PolygonTool") as ICommand;
Second: here is my test snippet that shows the chained edit operation (on the same layer):
/// <summary>
/// Fires once the user completes the on-screen sketch. In the context of a construction tool the sketch geometry
/// is used for the shape of the feature.
/// </summary>
/// <param name="geometry">The sketch geometry the user digitized on the screen.</param>
/// <returns></returns>
protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
{
// find and use the first polygon layer
var _polygonLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().Where(lyr => lyr.ShapeType == esriGeometryType.esriGeometryPolygon).FirstOrDefault();
if (_polygonLayer == null)
{
MessageBox.Show("Cannot find a Polygon layer to save constructed geometries");
}
if (geometry == null || _polygonLayer == null)
return Task.FromResult(false);
var dockPane = Module1.ActiveDockPane;
if (dockPane == null)
{
MessageBox.Show($@"Unable to find the Add Polygon dockpane");
}
return QueuedTask.Run(() =>
{
// create an edit operation
var editOperation = new EditOperation
{
Name = $@"Create polygon in '{_polygonLayer.Name}'",
ProgressMessage = "Working...",
CancelMessage = "Operation canceled",
ErrorMessage = "Error creating point"
};
long newObjectID = -1;
// update attributes
Dictionary<string, object> attributes = new Dictionary<string, object>
{
{ "TheString", "First edit operation" }
};
// queue the edit operation using the sketch geometry as the shape of the feature
editOperation.Create(_polygonLayer, geometry, object_id => newObjectID = object_id);
dockPane.UpdateStatusText($@"Created a polygon in '{_polygonLayer.Name}'");
//execute the operation
if (!editOperation.Execute())
{
return Task.FromResult(false);
}
// chain to create a new operation
var opChain = editOperation.CreateChainedOperation();
attributes["TheString"] = "Chained operation";
opChain.Modify (_polygonLayer, newObjectID, attributes);
return opChain.ExecuteAsync();
});
}
and here is the result, which shows that the chained edit did update the attribute table (by updating the "TheString" field with the "Chained operation" status:
Hello !
Thank you so much ! I work with the SDK 2.6 but it's not a problem. I adapted your code and it works ! I learnt so much things (EditOperation, SketchType, how to do a dock panel in ArcGis Pro).
Thanks again ! 🙂
I have one more question about the EditOperation (code below). I instantiated the EditOperation, then I use editOperation.create to create the new row and to fill it with attributes. If the attributes table panel is open, I see my new line. Nice ! After that, I create a chainedEditOperation to add the geometry with chainedEditOperation.Modify. The row is updated, but if the attributes table panel is open, the view is not updated. I have to close and open again the attributes table to see the geometry in the fields.
Is it possible to update the view like the "Create" method ?
Task t = QueuedTask.Run(() =>
{
// create an edit operation
var editOperation = new EditOperation
{
Name = $@"Create polygon in '{_polygonLayer.Name}'",
ProgressMessage = "Working...",
CancelMessage = "Operation canceled",
ErrorMessage = "Error creating point"
};
long newOid = -1;
Dictionary<string, object> attributes = new Dictionary<string, object>();
attributes.Add("Name", EntityNamePreview);
// queue the edit operation using the sketch geometry as the shape of the feature and keep the object id
editOperation.Create(_polygonLayer.GetTable(), attributes, oid => newOid = oid);
// if created, fill it with the new polygon
if (editOperation.Execute())
{
var chainedOperation = editOperation.CreateChainedOperation();
chainedOperation.Modify(_polygonLayer, newOid, PolygonCreated);
chainedOperation.Execute();
}
});
while (t.Status != TaskStatus.RanToCompletion) ;
Thank you !
I coded your sample snippet in the code below and also found a bug in my attached solution.
First be bug: The ICommand property in the viewmodel was not named properly it should have been named:
/// <summary>
/// hook existing ArcGIS Pro Tool Button
/// </summary>
public ICommand CmdCreatePolygon => FrameworkApplication.GetPlugInWrapper("CreatePolygon_PolygonTool") as ICommand;
Second: here is my test snippet that shows the chained edit operation (on the same layer):
/// <summary>
/// Fires once the user completes the on-screen sketch. In the context of a construction tool the sketch geometry
/// is used for the shape of the feature.
/// </summary>
/// <param name="geometry">The sketch geometry the user digitized on the screen.</param>
/// <returns></returns>
protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
{
// find and use the first polygon layer
var _polygonLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().Where(lyr => lyr.ShapeType == esriGeometryType.esriGeometryPolygon).FirstOrDefault();
if (_polygonLayer == null)
{
MessageBox.Show("Cannot find a Polygon layer to save constructed geometries");
}
if (geometry == null || _polygonLayer == null)
return Task.FromResult(false);
var dockPane = Module1.ActiveDockPane;
if (dockPane == null)
{
MessageBox.Show($@"Unable to find the Add Polygon dockpane");
}
return QueuedTask.Run(() =>
{
// create an edit operation
var editOperation = new EditOperation
{
Name = $@"Create polygon in '{_polygonLayer.Name}'",
ProgressMessage = "Working...",
CancelMessage = "Operation canceled",
ErrorMessage = "Error creating point"
};
long newObjectID = -1;
// update attributes
Dictionary<string, object> attributes = new Dictionary<string, object>
{
{ "TheString", "First edit operation" }
};
// queue the edit operation using the sketch geometry as the shape of the feature
editOperation.Create(_polygonLayer, geometry, object_id => newObjectID = object_id);
dockPane.UpdateStatusText($@"Created a polygon in '{_polygonLayer.Name}'");
//execute the operation
if (!editOperation.Execute())
{
return Task.FromResult(false);
}
// chain to create a new operation
var opChain = editOperation.CreateChainedOperation();
attributes["TheString"] = "Chained operation";
opChain.Modify (_polygonLayer, newObjectID, attributes);
return opChain.ExecuteAsync();
});
}
and here is the result, which shows that the chained edit did update the attribute table (by updating the "TheString" field with the "Chained operation" status:
Hello ! 🙂
I see where is my mistake !
Thank you again !!!