Workflow suggestions for moving a Graphic?

2108
3
Jump to solution
02-28-2017 09:31 AM
KeithGemeinhart1
New Contributor III

I have some graphics on the map (point geometries). What is the best way to move a single graphic with the mouse? I would like to click on to select, which is easy. I already have selection working. Then when the user clicks and drags the graphic, I want it to follow the mouse as it moves and remain where the user releases the mouse button. Essentially a typical operation for moving things around.

What is the best way to implement this in Runtime 100.0? Is there some way to inject an existing graphic into the sketch editor? I've thought about a workaround - making the exiting graphic invisible, using the sketch graphic as a temporary feedback mechanism, then when sketch editing ends, move the existing graphic and making it visible again. The temp graphic would be deleted at that point. That seems a little convoluted and hoping for a simpler method if it exists.

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JenniferNery
Esri Regular Contributor

You can use SketchEditor for this. Point geometry is updated either by tapping a new location or by dragging the graphic. StartAsync will return new geometry once you call Complete command. You can use Complete button or subscribe to GeometryChanged and let the handler execute CompleteCommand programmatically to get new geometry on mouse up.

        xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013">
    <Grid>
        <esri:MapView x:Name="MyMapView" />
        <StackPanel VerticalAlignment="Top"
                    HorizontalAlignment="Right">
            <Button Content="Edit"
                    Click="Button_Click" />
            <Button Content="Complete"
                    Command="{Binding ElementName=MyMapView, Path=SketchEditor.CompleteCommand}" />
        </StackPanel>
    </Grid>

In this sample code, I am using SketchEditor for two purposes:

1) to identify and select graphic for edit 

2) to update graphic geometry

Handle TaskCanceledException in case "Edit" button was clicked again, which will cancel previous StartAsync call.

        public MainWindow()
        {
            InitializeComponent();

            MyMapView.Map = new Map(Basemap.CreateTopographic());

            var overlay = new GraphicsOverlay() { RenderingMode = GraphicsRenderingMode.Static };
            overlay.Renderer = new SimpleRenderer(new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Colors.Blue, 12d));
            overlay.Graphics.Add(new Graphic(new MapPoint(0, 0, MyMapView.SpatialReference)));
            MyMapView.GraphicsOverlays.Add(overlay);


            //MyMapView.SketchEditor.GeometryChanged += SketchEditor_GeometryChanged;
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            Graphic graphic = null;
            try
            {
                foreach (var overlay in MyMapView.GraphicsOverlays)
                    overlay.ClearSelection();
                var mapPoint = await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Point, false) as MapPoint;
                var screenPoint = MyMapView.LocationToScreen(mapPoint);
                var results = await MyMapView.IdentifyGraphicsOverlaysAsync(screenPoint, 1, false, 1);
                var result = results?.FirstOrDefault();
                graphic = result?.Graphics?.FirstOrDefault();
                if (graphic == null)
                    return;
                graphic.IsSelected = true;
                graphic.IsVisible = false;
                var geometry = await MyMapView.SketchEditor.StartAsync(graphic.Geometry);
                graphic.Geometry = geometry;
            }
            catch (TaskCanceledException)
            {

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                if (graphic != null)
                    graphic.IsVisible = true;
            }
        }

        private void SketchEditor_GeometryChanged(object sender, GeometryChangedEventArgs e)
        {
            if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null))
                MyMapView.SketchEditor.CompleteCommand.Execute(null);
        }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

3 Replies
JenniferNery
Esri Regular Contributor

You can use SketchEditor for this. Point geometry is updated either by tapping a new location or by dragging the graphic. StartAsync will return new geometry once you call Complete command. You can use Complete button or subscribe to GeometryChanged and let the handler execute CompleteCommand programmatically to get new geometry on mouse up.

        xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013">
    <Grid>
        <esri:MapView x:Name="MyMapView" />
        <StackPanel VerticalAlignment="Top"
                    HorizontalAlignment="Right">
            <Button Content="Edit"
                    Click="Button_Click" />
            <Button Content="Complete"
                    Command="{Binding ElementName=MyMapView, Path=SketchEditor.CompleteCommand}" />
        </StackPanel>
    </Grid>

In this sample code, I am using SketchEditor for two purposes:

1) to identify and select graphic for edit 

2) to update graphic geometry

Handle TaskCanceledException in case "Edit" button was clicked again, which will cancel previous StartAsync call.

        public MainWindow()
        {
            InitializeComponent();

            MyMapView.Map = new Map(Basemap.CreateTopographic());

            var overlay = new GraphicsOverlay() { RenderingMode = GraphicsRenderingMode.Static };
            overlay.Renderer = new SimpleRenderer(new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Colors.Blue, 12d));
            overlay.Graphics.Add(new Graphic(new MapPoint(0, 0, MyMapView.SpatialReference)));
            MyMapView.GraphicsOverlays.Add(overlay);


            //MyMapView.SketchEditor.GeometryChanged += SketchEditor_GeometryChanged;
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            Graphic graphic = null;
            try
            {
                foreach (var overlay in MyMapView.GraphicsOverlays)
                    overlay.ClearSelection();
                var mapPoint = await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Point, false) as MapPoint;
                var screenPoint = MyMapView.LocationToScreen(mapPoint);
                var results = await MyMapView.IdentifyGraphicsOverlaysAsync(screenPoint, 1, false, 1);
                var result = results?.FirstOrDefault();
                graphic = result?.Graphics?.FirstOrDefault();
                if (graphic == null)
                    return;
                graphic.IsSelected = true;
                graphic.IsVisible = false;
                var geometry = await MyMapView.SketchEditor.StartAsync(graphic.Geometry);
                graphic.Geometry = geometry;
            }
            catch (TaskCanceledException)
            {

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                if (graphic != null)
                    graphic.IsVisible = true;
            }
        }

        private void SketchEditor_GeometryChanged(object sender, GeometryChangedEventArgs e)
        {
            if (MyMapView.SketchEditor.CompleteCommand.CanExecute(null))
                MyMapView.SketchEditor.CompleteCommand.Execute(null);
        }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
KeithGemeinhart1
New Contributor III

Thanks for this! A quick follow-up question. Is it possible to delete a vertex on a polyline? The previous version of runtime had a DeleteVertex command, but this one doesn't. However, after reviewing the docs (SketchEditor Properties), I see that you can pass a vertex to the DeleteCommand via the CommandParameter.

The problem is, how do I detect which vertex is selected?

0 Kudos
EricPfirman
New Contributor III

This solution works for points, but not for polygons. Do you have an example that will work for polygons? And lines?

0 Kudos