Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Add Graphics Interactively

Download Samples Repository

Description

Example of how to add Graphics to a GraphicsOverlay by drawing shapes on the map.The Editor.RequestShapeAsync method is used to manage map drawing and geometry creation.Symbols for the graphics are defined in XAML.

"Desktop" "Store" "Phone" Available for Desktop, Store, Phone

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.AddInteractively"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013">
    <Grid x:Name="LayoutGrid">
        <Grid.Resources>
            <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>

            <esri:SimpleMarkerSymbol x:Key="BluePointSymbol" Color="Blue" Style="Circle" Size="15" />
            <esri:SimpleLineSymbol x:Key="GreenLineSymbol" Color="Green" Style="Solid" Width="4" />
            <esri:SimpleFillSymbol x:Key="RedFillSymbol" Color="Red" Style="DiagonalCross">
                <esri:SimpleFillSymbol.Outline>
                    <esri:SimpleLineSymbol Color="Red" Style="Solid" Width="1" />
                </esri:SimpleFillSymbol.Outline>
            </esri:SimpleFillSymbol>
        </Grid.Resources>

        <esri:MapView x:Name="MyMapView" WrapAround="True">
			<esri:Map>
				<esri:ArcGISTiledMapServiceLayer
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer" />
				<esri:GraphicsLayer ID="graphicsLayer" />
			</esri:Map>
		</esri:MapView>

		<Border Background="White" BorderBrush="Black" BorderThickness="1"
			HorizontalAlignment="Right" VerticalAlignment="Top"
			Margin="30" Padding="20">
			<Border.Effect>
				<DropShadowEffect/>
			</Border.Effect>
			<StackPanel>
                <StackPanel>
                    <TextBlock Text="Graphic Type" FontSize="14" FontWeight="Bold" />

                    <ComboBox SelectedItem="{Binding CurrentDrawShape}" Margin="8,8,8,2" Padding="4"
                              SelectionChanged="ComboBox_SelectionChanged">
                        <esri:DrawShape>Point</esri:DrawShape>
                        <esri:DrawShape>Polyline</esri:DrawShape>
                        <esri:DrawShape>Polygon</esri:DrawShape>
                        <esri:DrawShape>Rectangle</esri:DrawShape>
                        <esri:DrawShape>Freehand</esri:DrawShape>
                        <esri:DrawShape>Arrow</esri:DrawShape>
                        <esri:DrawShape>Triangle</esri:DrawShape>
                        <esri:DrawShape>Ellipse</esri:DrawShape>
                        <esri:DrawShape>Circle</esri:DrawShape>
                        <esri:DrawShape>LineSegment</esri:DrawShape>
                        <esri:DrawShape>Envelope</esri:DrawShape>
                    </ComboBox>

                    <ToggleButton Margin="8" HorizontalAlignment="Center" Padding="6"
                              Width="125" FontWeight="Bold" IsThreeState="False"
                              IsChecked="{Binding InDrawMode}" Click="ToggleButton_Click">
                        <ToggleButton.Style>
                            <Style TargetType="{x:Type ToggleButton}">
                                <Style.Triggers>
                                    <Trigger Property="IsChecked" Value="True">
                                        <Setter Property="Content" Value="Exit Draw Mode" />
                                    </Trigger>
                                    <Trigger Property="IsChecked" Value="False">
                                        <Setter Property="Content" Value="Enter Draw Mode" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </ToggleButton.Style>
                    </ToggleButton>
                </StackPanel>

                <Border BorderBrush="Black" BorderThickness="1" Margin="4,8,4,4">
                    <StackPanel Orientation="Horizontal">
						<TextBlock Text="{Binding ElementName=MyMapView, Path=Map.Layers[graphicsLayer].Graphics.Count, StringFormat='Graphics Count:  {0}'}"
                                   Margin="4" Width="110" VerticalAlignment="Center" />
                        <Button Content="Clear" Click="ClearButton_Click" HorizontalAlignment="Right" />
                    </StackPanel>
                </Border>
            </StackPanel>
        </Border>

        <Border Background="White" BorderBrush="Black" BorderThickness="2" Margin="25"
                HorizontalAlignment="Center" VerticalAlignment="Bottom"
                Visibility="{Binding ElementName=MyMapView, Path=Editor.IsActive, Converter={StaticResource BooleanToVisibilityConverter}}">
            <TextBlock Text="Draw the graphic shape on the map." Margin="8" FontSize="14" />
        </Border>
    </Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Layers;
using Esri.ArcGISRuntime.Symbology;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.Samples.Desktop
{
	/// <summary>
	/// Example of how to add Graphics to a GraphicsOverlay by drawing shapes on the map.  The Editor.RequestShapeAsync method is used to manage map drawing and geometry creation.  Symbols for the graphics are defined in XAML.
	/// </summary>
	/// <title>Add Graphics Interactively</title>
	/// <category>Layers</category>
	/// <subcategory>Graphics Layers</subcategory>
	public partial class AddInteractively : UserControl, INotifyPropertyChanged
	{
		/// <summary>INotifyPropertyChanged notification</summary>
		public event PropertyChangedEventHandler PropertyChanged;

		private GraphicsLayer _graphicsLayer;

		private bool _inDrawMode;
		/// <summary>Is In Drawing Mode</summary>
		public bool InDrawMode
		{
			get { return _inDrawMode; }
			set
			{
				_inDrawMode = value;
				if (PropertyChanged != null)
					PropertyChanged(this, new PropertyChangedEventArgs("InDrawMode"));
			}
		}

		private DrawShape _currentDrawShape;
		/// <summary>Currently selected shape type</summary>
		public DrawShape CurrentDrawShape
		{
			get { return _currentDrawShape; }
			set
			{
				_currentDrawShape = value;
				if (PropertyChanged != null)
					PropertyChanged(this, new PropertyChangedEventArgs("CurrentDrawShape"));
			}
		}

		/// <summary>Construct Add Graphics Interactively sample control</summary>
		public AddInteractively()
		{
			InitializeComponent();

			DataContext = this;
			_currentDrawShape = DrawShape.Point;
			_graphicsLayer = MyMapView.Map.Layers["graphicsLayer"] as GraphicsLayer;
			_inDrawMode = false;
		}

		// Draw graphics infinitely
		private async Task AddGraphicsAsync()
		{
			await MyMapView.LayersLoadedAsync();

			while (InDrawMode)
			{
				// if the map is not in a valid state - quit and turn drawing mode off
				if (MyMapView.GetCurrentViewpoint(ViewpointType.BoundingGeometry).TargetGeometry.Extent == null)
				{
					InDrawMode = false;
					break;
				}

				await AddSingleGraphicAsync();
			}
		}

		// Draw and add a single graphic to the graphic layer
		private async Task AddSingleGraphicAsync()
		{
			try
			{
				Symbol symbol = null;
				switch (CurrentDrawShape)
				{
					case DrawShape.Point:
						symbol = LayoutGrid.Resources["BluePointSymbol"] as Symbol;
						break;

					case DrawShape.LineSegment:
					case DrawShape.Freehand:
					case DrawShape.Polyline:
						symbol = LayoutGrid.Resources["GreenLineSymbol"] as Symbol;
						break;

					case DrawShape.Arrow:
					case DrawShape.Circle:
					case DrawShape.Ellipse:
					case DrawShape.Polygon:
					case DrawShape.Rectangle:
					case DrawShape.Triangle:
					case DrawShape.Envelope:
						symbol = LayoutGrid.Resources["RedFillSymbol"] as Symbol;
						break;
				}

				// wait for user to draw the shape
				var geometry = await MyMapView.Editor.RequestShapeAsync(CurrentDrawShape, symbol);

				// add the new graphic to the graphic layer
				var graphic = new Graphic(geometry, symbol);
				_graphicsLayer.Graphics.Add(graphic);
			}
			catch (TaskCanceledException)
			{
				// Ignore cancellations from selecting new shape type
			}
			catch (Exception ex)
			{
				MessageBox.Show("Error drawing graphic: " + ex.Message, "Add Graphic Interactively");
			}
		}

		// Cancel the current shape drawing (if in Editor.RequestShapeAsync) when the shape type has changed
		private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			if (MyMapView.Editor.IsActive)
				MyMapView.Editor.Cancel.Execute(null);
		}

		// Cancel the current shape drawing (if in Editor.RequestShapeAsync)
		//  and initiate new graphic adding if drawing mode is on
		private void ToggleButton_Click(object sender, RoutedEventArgs e)
		{
			if (MyMapView.Editor.IsActive)
				MyMapView.Editor.Cancel.Execute(null);

			if (InDrawMode)
			{
				var _x = AddGraphicsAsync();
			}
		}

		private void ClearButton_Click(object sender, RoutedEventArgs e)
		{
			_graphicsLayer.Graphics.Clear();
		}
	}
}
Feedback on this topic?