Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Dynamic Layer Edit Geometry

Download Samples Repository

Description

Demonstrates how to selectively import and update feature geometry in dynamic layer.

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

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.DynamicLayerEditGeometry"
             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">
    <UserControl.Resources>
        <!-- Transparent symbol highlights on selection -->
        <esri:SimpleFillSymbol x:Key="TransparentFillSymbol"
                               Color="Transparent" />
        <esri:SimpleRenderer x:Key="HighlightRenderer"
                             Symbol="{StaticResource TransparentFillSymbol}" />
    </UserControl.Resources>
    <Grid>
        <esri:MapView x:Name="MyMapView"
                      MapViewTapped="MyMapView_MapViewTapped">
            <esri:Map InitialViewpoint="-13279585.9811197,4010136.34579502,-12786146.5545795,4280849.94238526">
                <esri:ArcGISTiledMapServiceLayer ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
                <!-- Renders features at current extent -->
				<esri:ArcGISDynamicMapServiceLayer ID="RecreationalArea"
                                                   VisibleLayers="2"
                                                   ServiceUri="http://sampleserver6.arcgisonline.com/arcgis/rest/services/LocalGovernment/Recreation/MapServer" />
            </esri:Map>
            <esri:MapView.GraphicsOverlays>
                <!-- Highlights one feature at a time -->
                <esri:GraphicsOverlay ID="Highlighter"
                                      Renderer="{StaticResource HighlightRenderer}" />
            </esri:MapView.GraphicsOverlays>
        </esri:MapView>
        <!-- Used for geometry editing -->
        <Border Background="White"
                BorderBrush="Black"
                BorderThickness="1"
                HorizontalAlignment="Right"
                VerticalAlignment="Top"
                Margin="30"
                Padding="20">
            <Border.Effect>
                <DropShadowEffect />
            </Border.Effect>
            <StackPanel Orientation="Horizontal"
                        DataContext="{Binding ElementName=MyMapView, Path=Editor}">
                <Button Content="Edit"
                        Margin="2"
                        IsEnabled="False"
                        x:Name="EditButton"
                        Click="EditButton_Click" />
                <Button Content="Delete Vertex"
                        Margin="2"
                        Command="{Binding DeleteVertex}" />
                <Button Content="Undo"
                        Margin="2"
                        Command="{Binding Undo}" />
                <Button Content="Redo"
                        Margin="2"
                        Command="{Binding Redo}" />
                <Button Content="Complete"
                        Margin="2"
                        Command="{Binding Complete}" />
                <Button Content="Cancel"
                        Margin="2"
                        Command="{Binding Cancel}" />
            </StackPanel>
        </Border>
        <Border Background="White"
                BorderBrush="Black"
                BorderThickness="1"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                Margin="30"
                Padding="20">
            <Border.Effect>
                <DropShadowEffect />
            </Border.Effect>
            <TextBlock Text="Click on a feature to select and edit its geometry."
                       Width="200"
                       TextAlignment="Left"
                       Margin="30,20,20,30"
                       TextWrapping="Wrap" />
        </Border>
    </Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Layers;
using Esri.ArcGISRuntime.Tasks.Query;
using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.Samples.Desktop
{
    /// <summary>
    /// Demonstrates how to selectively import and update feature geometry in dynamic layer.
    /// </summary>
    /// <title>Dynamic Layer Edit Geometry</title>
    /// <category>Editing</category>
    public partial class DynamicLayerEditGeometry : UserControl
    {
        // Editing is done through this table.
        private ServiceFeatureTable table;

        public DynamicLayerEditGeometry()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Identifies feature to highlight.
        /// </summary>
        private async void MyMapView_MapViewTapped(object sender, MapViewInputEventArgs e)
        {
            // Ignore tap events while in edit mode so we do not interfere with edit geometry.
            if (MyMapView.Editor.IsActive)
                return;

            // Get current viewpoints extent from the MapView
            var currentViewpoint = MyMapView.GetCurrentViewpoint(ViewpointType.BoundingGeometry);
            var viewpointExtent = currentViewpoint.TargetGeometry.Extent;

            var layer = MyMapView.Map.Layers["RecreationalArea"] as ArcGISDynamicMapServiceLayer;
            var task = new IdentifyTask(new Uri(layer.ServiceUri));
            var mapPoint = MyMapView.ScreenToLocation(e.Position);
            var parameter = new IdentifyParameters(mapPoint, viewpointExtent, 2, (int)MyMapView.ActualHeight, (int)MyMapView.ActualWidth);

            // Clears map of any highlights.
            var overlay = MyMapView.GraphicsOverlays["Highlighter"] as GraphicsOverlay;
            overlay.Graphics.Clear();

            SetGeometryEditor();

            string message = null;
            try
            {
                // Performs an identify and adds feature result as selected into overlay.
                var result = await task.ExecuteAsync(parameter);
                if (result == null || result.Results == null || result.Results.Count < 1)
                    return;
                var graphic = (Graphic)result.Results[0].Feature;
                graphic.IsSelected = true;
                overlay.Graphics.Add(graphic);

                // Prepares geometry editor.
                var featureID = Convert.ToInt64(graphic.Attributes["Objectid"], CultureInfo.InvariantCulture);
                SetGeometryEditor(featureID);
            }
            catch (Exception ex)
            {
                message = ex.Message;
            }
            if (!string.IsNullOrWhiteSpace(message))
                MessageBox.Show(message);
        }

        /// <summary>
        /// Prepares geometry editor for editing.
        /// </summary>
        private void SetGeometryEditor(long featureID = 0)
        {
            EditButton.Tag = featureID;
            EditButton.IsEnabled = featureID == 0 ? false : true;
        }

        /// <summary>
        /// Enables geometry editing, submits geometry edit back to the server and refreshes dynamic layer.
        /// </summary>
        private async void EditButton_Click(object sender, RoutedEventArgs e)
        {
            var layer = MyMapView.Map.Layers["RecreationalArea"] as ArcGISDynamicMapServiceLayer;
            var overlay = MyMapView.GraphicsOverlays["Highlighter"] as GraphicsOverlay;
            var featureID = (long)EditButton.Tag;
            string message = null;
            try
            {
                // Hides graphic from overlay and dynamic layer while its geometry is being modified.
                overlay.Graphics.Clear();
                // Negative IDs indicate they do not exist on server yet.
                if (featureID > 0)
                {
                    if (layer.LayerDefinitions == null)
                        layer.LayerDefinitions = new ObservableCollection<LayerDefinition>();
                    else
                        layer.LayerDefinitions.Clear();
                    layer.LayerDefinitions.Add(new LayerDefinition()
                    {
                        LayerID = layer.VisibleLayers[0],
                        Definition = string.Format("Objectid <> {0}", featureID)
                    });
                }
                if (table == null)
                {
                    // Creates table based on visible layer of dynamic layer 
                    // using FeatureServer specifying shape field to enable editing.
                    var id = layer.VisibleLayers[0];
                    var url = layer.ServiceUri.Replace("MapServer", "FeatureServer");
                    url = string.Format("{0}/{1}", url, id);
                    table = await ServiceFeatureTable.OpenAsync(new Uri(url), null, MyMapView.SpatialReference);
                }
                // Retrieves feature identified by ID and updates its geometry 
                // using GeometryEngine to correct ring orientation.
                var feature = await table.QueryAsync(featureID);
                var geometry = await MyMapView.Editor.EditGeometryAsync(feature.Geometry);
                feature.Geometry = GeometryEngine.Simplify(geometry);
                await table.UpdateAsync(feature);
                if (table.HasEdits)
                {
                    // Pushes geometry edits back to the server.
                    var result = await table.ApplyEditsAsync();
                    if (result.UpdateResults == null || result.UpdateResults.Count < 1)
                        return;
                    var updateResult = result.UpdateResults[0];
                    if (updateResult.Error != null)
                        message = updateResult.Error.Message;
                }

            }
            catch (TaskCanceledException te)
            {
                // Handles canceling out of Editor.
            }
            catch (Exception ex)
            {
                message = ex.Message;
            }
            finally
            {
                SetGeometryEditor();
                if (layer.LayerDefinitions != null)
                {
                    layer.LayerDefinitions.Clear();
                    // Refreshes layer to reflect geometry edits.
                    layer.Invalidate();
                }
            }
            if (!string.IsNullOrWhiteSpace(message))
                MessageBox.Show(message);
        }
    }
}
Feedback on this topic?