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?