Hello Thank you for any help.
To get right to it:
Summary:
I am trying to figure out the work flow on creating and editing a multi segment line in esri .net for wpf:
Esri Version: 100.15.0
.Net Framework 4.7.2
Details:
We are using the Sketcheditor to create/edit our geometry for our Features in our end user application. We received a request to add the ability to create and edit multi segment polylines. I have been digging through Documentation trying to see if there is a pre-built solution or workflow. I have included out Sketch editor code. Not sure what other information i need to include. Let me know Thank you
public partial class SketchControl : UserControl, INotifyPropertyChanged
{
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var propertyChangedHandler = PropertyChanged;
if (propertyChangedHandler != null)
propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
private ALViewModel _vm;
private bool _selectFromMapEnabled = true;
public bool selectFromMapEnabled
{
get { return _selectFromMapEnabled; }
set
{
_selectFromMapEnabled = value;
OnPropertyChanged();
}
}
private PolygonBuilder _PolygonBuilder;
public PolygonBuilder PolygonBuilder
{
get { return _PolygonBuilder; }
set
{
_PolygonBuilder = value;
OnPropertyChanged();
}
}
private bool _selectingFromMap = false;
public bool selectingFromMap
{
get { return _selectingFromMap; }
set
{
_selectingFromMap = value;
OnPropertyChanged();
}
}
private double _animateTo = 1.0;
public double animateTo
{
get { return _animateTo; }
set
{
_animateTo = value;
OnPropertyChanged();
}
}
public PolylineBuilder lineBuilder;
// Need dependency objects
public static readonly DependencyProperty SelectFromLayerProperty =
DependencyProperty.Register("SelectFromLayer", typeof(string), typeof(SketchControl), new FrameworkPropertyMetadata(null));
public string SelectFromLayer
{
get { return (string)GetValue(SelectFromLayerProperty); }
set { SetValue(SelectFromLayerProperty, value); }
}
public static readonly DependencyProperty AllowSelectFromMapProperty =
DependencyProperty.Register("AllowSelectFromMap", typeof(bool), typeof(SketchControl), new FrameworkPropertyMetadata(null));
public bool AllowSelectFromMap
{
get { return (bool)GetValue(AllowSelectFromMapProperty); }
set { SetValue(AllowSelectFromMapProperty, value); }
}
public SketchControl()
{
//var sketchEditor = _vm.MapControlMap.SketchEditor;
_vm = FindResource("ALvm") as ALViewModel;
InitializeComponent();
// Set the sketch editor as the page's data context
DataContext = _vm.MapControlMap.SketchEditor;
_vm.MapControlMap.SketchEditor.CompleteCommand.CanExecuteChanged += CanExecuteChanged;
_vm.MapControlMap.SketchEditor.GeometryChanged += SEGeometryChanged;
_vm.MapControlMap.SketchEditor.CancelCommand.CanExecuteChanged += cancelSketch;
}
private void cancelSketch(object sender, EventArgs e)
{
ICommand command = (ICommand)sender;
if (command == _vm.MapControlMap.SketchEditor.CancelCommand)
{
//_vm.WaitIndicatorText = "Feature added";
//_vm.WaitIndicatorVisible = false;
//var sketchEditor = _vm.MapControlMap.SketchEditor;
//sketchEditor.CancelCommand.Execute(null);
selectFromMapEnabled = true;
selectingFromMap = false;
}
}
private async void Sb_Start_Click(object sender, RoutedEventArgs e)
{
if (_vm.Current_Feature.Geometry == null)
{
// Create Geometry
}
else
{
// Edit Geometry
SketchEditConfiguration sem = new SketchEditConfiguration();
sem.AllowMove = true;
sem.AllowRotate = true;
sem.AllowVertexEditing = true;
sem.ResizeMode = SketchResizeMode.Uniform;
sem.VertexEditMode = SketchVertexEditMode.InteractionEdit;
sem.
Geometry geometry = _vm.Current_Feature.Geometry;
SketchCreationMode sm = ALViewModel.geometrytype2SketchCreationMode(geometry.GeometryType);
try
{
_vm.MapControlMap.Cursor = Cursors.Pen;
// If the map has a different spatial reference than the feature layer, we must reproject the feature layer to match.
// Otherwise, the SketchEditor will fail.
SpatialReference old_sr = geometry.SpatialReference;
geometry = GeometryEngine.Project(geometry, _vm.MapControlMap.SpatialReference);
_vm.MapControlMap.SketchEditor.IsVisible = true;
geometry = await _vm.MapControlMap.SketchEditor.StartAsync(geometry, sm, sem);
_vm.MapControlMap.SketchEditor.IsVisible = false;
// Reproject the edited geometry back to the original spatial reference.
_vm.Current_Feature.Geometry = GeometryEngine.Project(geometry, old_sr);
}
catch (TaskCanceledException)
{
// Ignore ... let the user cancel drawing
}
catch (Exception ex)
{
// Report exceptions
MessageBox.Show("Error drawing graphic shape: " + ex.Message);
}
}
}
private void CanExecuteChanged(object sender, EventArgs e)
{
ICommand command = (ICommand)sender;
if (command == _vm.MapControlMap.SketchEditor.UndoCommand)
{
}
else if (command == _vm.MapControlMap.SketchEditor.RedoCommand)
{
}
else if (command == _vm.MapControlMap.SketchEditor.CompleteCommand)
{
if (_vm.MapControlMap.SketchEditor.CompleteCommand.CanExecute(null))
{
// Editing
}
else
{
// Not Editing
}
}
}
private void SEGeometryChanged(object sender, EventArgs e)
{
GeometryChangedEventArgs geo = e as GeometryChangedEventArgs;
if (selectFromMapEnabled && selectingFromMap && geo.OldGeometry == null)
{
// We attempted to select some geometry. Is it valid?
if (geo.NewGeometry != null)
{
MapPoint queryPoint = ((GeometryChangedEventArgs)e).NewGeometry.Extent.GetCenter();
Geometry gm = Esri.ArcGISRuntime.Geometry.GeometryEngine.Buffer(queryPoint, 2);
FeatureLayer layer = (FeatureLayer)_vm.MapControlMap.Map.OperationalLayers.FirstOrDefault(x => x.Name == SelectFromLayer);
//FeatureLayer layer = (FeatureLayer)_vm.MapControlMap.Map.OperationalLayers.Where(x => x.Name == "TITLES").FirstOrDefault();
var query = new QueryParameters();
//query.Geometry = queryPoint;
query.Geometry = gm;
query.MaxFeatures = 1;
query.SpatialRelationship = SpatialRelationship.Intersects;
query.WhereClause = layer.DefinitionExpression;
Feature selectedfeature = layer.FeatureTable.QueryFeaturesAsync(query).Result.FirstOrDefault();
Feature f = selectedfeature;
if (f != null)
{
_vm.MapControlMap.SketchEditor.GeometryChanged -= SEGeometryChanged;
_vm.MapControlMap.SketchEditor.ReplaceGeometry(f.Geometry);
_vm.MapControlMap.SketchEditor.GeometryChanged += SEGeometryChanged;
// Need to populate NOTIFICATION values from TITLES
_vm.Sketch_Selection = f;
selectFromMapEnabled = false;
}
else
{
// REMOVE or RECREATE the NOTIFICATION to erase the values added when we selected a TITLE
_vm.MapControlMap.SketchEditor.UndoCommand.Execute(null);
}
}
}
else
{
if (geo.NewGeometry != null)
{
selectFromMapEnabled = false;
}
else
{
selectFromMapEnabled = true;
_vm.Sketch_Selection = null;
}
}
}
private async Task NewSegment()
{
}
private async void Sb_Complete_Click(object sender, RoutedEventArgs e)
{
var sketchEditor = _vm.MapControlMap.SketchEditor;
//Need to check for valid geometry!
bool iv = false; // assume bad geometry
if (_vm.MapControlMap.SketchEditor.Geometry != null)
{
switch (_vm.MapControlMap.SketchEditor.Geometry.GetType().ToString())
{
case "Esri.ArcGISRuntime.Geometry.MapPoint":
{
// Well, if the geometry is not null, it must be valid. :)
iv = true;
break;
}
case "Esri.ArcGISRuntime.Geometry.Polyline":
{
Geometry pl_test = (_vm.MapControlMap.SketchEditor.Geometry);
PolylineBuilder pl_pb = new PolylineBuilder(_vm.Map.SpatialReference);
pl_pb.ReplaceGeometry((Polyline)pl_test);
iv = pl_pb.IsSketchValid;
break;
}
case "Esri.ArcGISRuntime.Geometry.Polygon":
{
Geometry pl_test = (_vm.MapControlMap.SketchEditor.Geometry);
PolygonBuilder pl_pb = new PolygonBuilder(_vm.Map.SpatialReference);
pl_pb.ReplaceGeometry((Polygon)pl_test);
iv = pl_pb.IsSketchValid;
break;
}
default:
break;
}
}
if (_vm.Current_Feature == null && iv)
{
try
{
_vm.WaitIndicatorText = "Adding Feature";
_vm.WaitIndicatorVisible = true;
await _vm.AddFeature(_vm.MapControlMap.SketchEditor.Geometry, _vm.FeatureLayerToCreate, _vm.Sketch_Selection, _vm.Sketch_Clone, true);
// Populate LANDOWNER data from PARCEL_INFO if needed
if (_vm.FeatureLayerToCreate.Name == "LANDOWNER")
{
ALViewModel.Changed_By oldChangedBy = _vm.Current_Changed_By;
_vm.Current_Changed_By = ALViewModel.Changed_By.Map_Selection;
//await add_landowners(geometry);
// update the PARCEL_ID and CONTACT_STATUS fields at a minimum
update_LANDOWNERS(_vm.Current_Feature);
_vm.Current_Changed_By = oldChangedBy;
}
//string[] array = { "POINT_WORK", "LINE_WORK", "POLY_WORK" };
//if (array.Contains(_vm.FeatureLayerToCreate.Name.ToUpper()))
//{
// ALViewModel.Changed_By oldChangedBy = _vm.Current_Changed_By;
// _vm.Current_Changed_By = ALViewModel.Changed_By.Map_Selection;
// _vm.Current_Feature.Attributes["REMOVE_QTY"] = 1;
// _vm.Current_Changed_By = oldChangedBy;
//}
_vm.WaitIndicatorText = "Feature added";
_vm.WaitIndicatorVisible = false;
sketchEditor.CompleteCommand.Execute(null);
//_vm.MapControlMap.SketchEditor.Stop();
}
catch (Exception ex)
{
_vm.WaitIndicatorText = "Feature added";
_vm.WaitIndicatorVisible = false;
sketchEditor.CancelCommand.Execute(null);
selectFromMapEnabled = true;
selectingFromMap = false;
}
}
else
{
if (_vm.Current_Feature != null)
{
_vm.Current_Feature.Geometry = _vm.MapControlMap.SketchEditor.Geometry;
}
//await _vm.Save_CurrentFeature();
else
{
// No valid geometry. Keep editing graphic.
MessageBox.Show("No valid geometry. Please continue editing.", "Error", MessageBoxButton.OK);
}
//sketchEditor.CompleteCommand.Execute(null);
}
selectFromMapEnabled = true;
selectingFromMap = false;
//sketchEditor.CompleteCommand.Execute(null);
}
private async void Sb_Select_Click(object sender, RoutedEventArgs e)
{
if (_vm.MapControlMap.SketchEditor.Geometry == null)
{
selectingFromMap = !selectingFromMap;
}
if (selectingFromMap == true)
animateTo = .5;
else
{
animateTo = 1;
}
}
Hi @ThomasZanis, have you seen our Create and Edit Geometries sample on our Developers site? This lays out a workflow for creating any geometries you'll need, including multi-segment polylines.
Just wanted to add that sample uses the new GeometryEditor introduced in 200.3. The old SketchEditor that was available in 100.15 did not fully support multi-part geometries.
Hello, Thank you for your reply. I have gone through the documentation for 100.15 and did not find anything. Version 200+ would be a perfect solution, but we can not upgrade to 200 just yet.