Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Sketch on map

This code sample is available for these platforms:
View Sample on GitHub

Use the Sketch Editor to edit or sketch a new point, line, or polygon geometry on to a map.

screenshot

Use case

A field worker could annotate features of interest on a map (via the GUI) such as location of dwellings (marked as points), geological features (polylines), or areas of glaciation (polygons).

How to use the sample

Click 'Draw/Edit', then choose which geometry type to sketch.

Use the control panel to undo or redo changes made to the sketch and to complete the sketch. There is also the option to select a saved graphic and edit its geometry using the Sketch Editor. The graphics overlay can be cleared using the clear button.

Relevant API

  • Geometry
  • Graphic
  • GraphicsOverlay
  • MapView
  • SketchCreationMode
  • SketchEditor

Tags

Geometry, Graphic, GraphicsOverlay, SketchCreationMode, SketchEditor, draw, edit

Sample Code

<UserControl
    x:Class="ArcGISRuntime.UWP.Samples.SketchOnMap.SketchOnMap"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:esriUI="using:Esri.ArcGISRuntime.UI.Controls">
    <Grid>
        <esriUI:MapView x:Name="MyMapView" />
        <CommandBar OverflowButtonVisibility="Collapsed">
            <AppBarButton AllowFocusOnInteraction="True">
                <AppBarButton.Content>
                    <TextBlock HorizontalAlignment="Center" Text="Draw/Edit" />
                </AppBarButton.Content>
                <AppBarButton.Flyout>
                    <Flyout x:Name="DrawToolsFlyout">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="5" />
                                <RowDefinition Height="35" />
                                <RowDefinition Height="35" />
                                <RowDefinition Height="35" />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <TextBlock
                                Grid.Row="1"
                                Grid.Column="0"
                                HorizontalAlignment="Right"
                                VerticalAlignment="Center"
                                FontSize="12"
                                Text="Sketch shape:" />
                            <ComboBox
                                x:Name="SketchModeComboBox"
                                Grid.Row="1"
                                Grid.Column="1"
                                Margin="2"
                                HorizontalAlignment="Stretch"
                                VerticalAlignment="Center"
                                FontSize="12" />
                            <Button
                                Grid.Row="2"
                                Grid.Column="1"
                                Width="100"
                                Height="30"
                                Margin="2"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Top"
                                Click="DrawButtonClick"
                                Content="Draw"
                                FontSize="12" />
                            <Button
                                x:Name="EditButton"
                                Grid.Row="3"
                                Grid.Column="1"
                                Width="100"
                                Height="30"
                                Margin="2"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Top"
                                Click="EditButtonClick"
                                Content="Edit"
                                FontSize="12"
                                IsEnabled="False" />
                        </Grid>
                    </Flyout>
                </AppBarButton.Flyout>
            </AppBarButton>
            <AppBarButton Command="{Binding UndoCommand}">
                <AppBarButton.Content>
                    <TextBlock HorizontalAlignment="Center" Text="Undo" />
                </AppBarButton.Content>
            </AppBarButton>
            <AppBarButton Command="{Binding RedoCommand}">
                <AppBarButton.Content>
                    <TextBlock HorizontalAlignment="Center" Text="Redo" />
                </AppBarButton.Content>
            </AppBarButton>
            <AppBarButton Command="{Binding CompleteCommand}">
                <AppBarButton.Content>
                    <TextBlock HorizontalAlignment="Center" Text="Complete" />
                </AppBarButton.Content>
            </AppBarButton>
            <AppBarButton x:Name="ClearButton" Click="ClearButtonClick">
                <AppBarButton.Content>
                    <TextBlock HorizontalAlignment="Center" Text="Clear" />
                </AppBarButton.Content>
            </AppBarButton>
        </CommandBar>
    </Grid>
</UserControl>
// Copyright 2017 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific 
// language governing permissions and limitations under the License.

using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Drawing;
using Windows.UI.Popups;
using Windows.UI.Xaml;

namespace ArcGISRuntime.UWP.Samples.SketchOnMap
{
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        "Sketch graphics on the map",
        "GraphicsOverlay",
        "This sample demonstrates how to interactively sketch and edit graphics in the map view and display them in a graphics overlay. You can sketch a variety of geometry types and undo or redo operations.",
        "1. Click the 'Sketch' button.\n2. Choose a sketch type from the drop down list.\n3. Click the 'Draw' button and click in the map view to create the sketch.\n4. While sketching, you can undo/redo operations.\n5. Click 'Done' to finish the sketch.\n6. To edit a graphic, click 'Draw/Edit', then 'Edit'. Select a graphic in the map to start editing.\n7. Make edits then click 'Done' to finish editing.")]
    public sealed partial class SketchOnMap
    {
        // Graphics overlay to host sketch graphics
        private GraphicsOverlay _sketchOverlay;

        public SketchOnMap()
        {
            InitializeComponent();

            // Call a function to set up the map and sketch editor 
            Initialize();
        }

        private void Initialize()
        {
            // Create a light gray canvas map
            Map myMap = new Map(Basemap.CreateLightGrayCanvas());

            // Create graphics overlay to display sketch geometry
            _sketchOverlay = new GraphicsOverlay();
            MyMapView.GraphicsOverlays.Add(_sketchOverlay);

            // Assign the map to the MapView
            MyMapView.Map = myMap;

            // Fill the combo box with choices for the sketch modes (shapes)
            SketchModeComboBox.ItemsSource = System.Enum.GetValues(typeof(SketchCreationMode));
            SketchModeComboBox.SelectedIndex = 0;

            // Set the sketch editor as the page's data context
            DataContext = MyMapView.SketchEditor;
        }

        #region Graphic and symbol helpers
        private Graphic CreateGraphic(Esri.ArcGISRuntime.Geometry.Geometry geometry)
        {
            // Create a graphic to display the specified geometry
            Symbol symbol = null;
            switch (geometry.GeometryType)
            {
                // Symbolize with a fill symbol
                case GeometryType.Envelope:
                case GeometryType.Polygon:
                    {
                        symbol = new SimpleFillSymbol()
                        {
                            Color = Color.Red,
                            Style = SimpleFillSymbolStyle.Solid
                        };
                        break;
                    }
                // Symbolize with a line symbol
                case GeometryType.Polyline:
                    {
                        symbol = new SimpleLineSymbol()
                        {
                            Color = Color.Red,
                            Style = SimpleLineSymbolStyle.Solid,
                            Width = 5d
                        };
                        break;
                    }
                // Symbolize with a marker symbol
                case GeometryType.Point:
                case GeometryType.Multipoint:
                    {

                        symbol = new SimpleMarkerSymbol()
                        {
                            Color = Color.Red,
                            Style = SimpleMarkerSymbolStyle.Circle,
                            Size = 15d
                        };
                        break;
                    }
            }

            // pass back a new graphic with the appropriate symbol
            return new Graphic(geometry, symbol);
        }

        private async Task<Graphic> GetGraphicAsync()
        {
            // Wait for the user to click a location on the map
            MapPoint mapPoint = (MapPoint)await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Point, false);

            // Convert the map point to a screen point
            var screenCoordinate = MyMapView.LocationToScreen(mapPoint);

            // Identify graphics in the graphics overlay using the point
            IReadOnlyList<IdentifyGraphicsOverlayResult> results = await MyMapView.IdentifyGraphicsOverlaysAsync(screenCoordinate, 2, false);

            // If results were found, get the first graphic
            Graphic graphic = null;
            IdentifyGraphicsOverlayResult idResult = results.FirstOrDefault();
            if (idResult != null && idResult.Graphics.Count > 0)
            {
                graphic = idResult.Graphics.FirstOrDefault();
            }

            // Return the graphic (or null if none were found)
            return graphic;
        }
        #endregion

        private async void DrawButtonClick(object sender, RoutedEventArgs e)
        {
            try
            {
                // Set the focus to the map view(close the flyout panel)
                DrawToolsFlyout.Hide();

                // Let the user draw on the map view using the chosen sketch mode
                SketchCreationMode creationMode = (SketchCreationMode)SketchModeComboBox.SelectedItem;
                Esri.ArcGISRuntime.Geometry.Geometry geometry = await MyMapView.SketchEditor.StartAsync(creationMode, true);

                // Create and add a graphic from the geometry the user drew
                Graphic graphic = CreateGraphic(geometry);
                _sketchOverlay.Graphics.Add(graphic);

                // Enable/disable the clear and edit buttons according to whether or not graphics exist in the overlay
                ClearButton.IsEnabled = _sketchOverlay.Graphics.Count > 0;
                EditButton.IsEnabled = _sketchOverlay.Graphics.Count > 0;
            }
            catch (TaskCanceledException)
            {
                // Ignore ... let the user cancel drawing
            }
            catch (Exception ex)
            {
                // Report exceptions
                MessageDialog dialog = new MessageDialog("Error drawing graphic shape: " + ex.Message);
                await dialog.ShowAsync();
            }
        }

        private void ClearButtonClick(object sender, RoutedEventArgs e)
        {
            // Remove all graphics from the graphics overlay
            _sketchOverlay.Graphics.Clear();

            // Cancel any uncompleted sketch
            if (MyMapView.SketchEditor.CancelCommand.CanExecute(null))
            {
                MyMapView.SketchEditor.CancelCommand.Execute(null);
            }

            // Disable buttons that require graphics
            ClearButton.IsEnabled = false;
            EditButton.IsEnabled = false;
        }

        private async void EditButtonClick(object sender, RoutedEventArgs e)
        {
            try
            {
                // Set the focus to the map view(close the flyout panel)
                DrawToolsFlyout.Hide();

                // Allow the user to select a graphic
                Graphic editGraphic = await GetGraphicAsync();
                if (editGraphic == null) { return; }

                // Let the user make changes to the graphic's geometry, await the result (updated geometry)
                Geometry newGeometry = await MyMapView.SketchEditor.StartAsync(editGraphic.Geometry);

                // Display the updated geometry in the graphic
                editGraphic.Geometry = newGeometry;
            }
            catch (TaskCanceledException)
            {
                // Ignore ... let the user cancel editing
            }
            catch (Exception ex)
            {
                // Report exceptions
                MessageDialog dialog = new MessageDialog("Error editing shape: " + ex.Message);
                await dialog.ShowAsync();
            }
        }
    }
}