Edit Attachment

Download Samples Repository

Description

Demonstrates how to update feature attachments in feature layer.

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

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.EditAttachment"
             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>
        <esri:MapView x:Name="MyMapView"
                      MapViewTapped="MyMapView_MapViewTapped">
            <esri:Map InitialViewpoint="-122.4406073721, 37.7566097907,-122.4130971868, 37.78197420877,4326">
                <esri:ArcGISTiledMapServiceLayer ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
                <!-- Makes all features at current extent available for editing -->
                <esri:FeatureLayer ID="Incidents">
                    <esri:ServiceFeatureTable ServiceUri="http://sampleserver6.arcgisonline.com/arcgis/rest/services/SF311/FeatureServer/0" />
                </esri:FeatureLayer>
            </esri:Map>
        </esri:MapView>
        <!-- Used for attachment editing -->
        <Border Background="White"
                BorderBrush="Black"
                BorderThickness="1"
                HorizontalAlignment="Right"
                VerticalAlignment="Top"
                Margin="30"
                Padding="20">
            <Border.Effect>
                <DropShadowEffect />
            </Border.Effect>
            <StackPanel>
                <Button x:Name="AddButton"
                        Content="Add"
						IsEnabled="False"
                        Margin="2"
                        Click="AddButton_Click" 
                        HorizontalAlignment="Left"/>
                <ListBox x:Name="AttachmentList"
                         IsEnabled="False"
                         ScrollViewer.VerticalScrollBarVisibility="Auto"
                         ScrollViewer.HorizontalScrollBarVisibility="Auto"
                         Height="200"
                         Width="200"
                         Margin="2">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding Name}"
                                           Width="50"
                                           TextTrimming="WordEllipsis" />
                                <Button Content="Open"
                                        Margin="2"
                                        Click="OpenButton_Click" />
                                <Button Content="Update"
                                        Margin="2"
                                        Click="UpdateButton_Click" />
                                <Button Content="Delete"
                                        Margin="2"
                                        Click="DeleteButton_Click" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </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 attachments."
                       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.Layers;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;

namespace ArcGISRuntime.Samples.Desktop
{
	/// <summary>
	/// Demonstrates how to update feature attachments in feature layer.
	/// </summary>
	/// <title>Edit Attachment</title>
	/// <category>Editing</category>
	public partial class EditAttachment : UserControl
	{
		public EditAttachment()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Selects feature for editing and query its attachments.
		/// </summary>
		private async void MyMapView_MapViewTapped(object sender, MapViewInputEventArgs e)
		{
			var layer = MyMapView.Map.Layers["Incidents"] as FeatureLayer;
			var table = (ArcGISFeatureTable)layer.FeatureTable;
			layer.ClearSelection();
			SetAttachmentEditor();
			string message = null;
			try
			{
				// Performs hit test on layer to select feature.
				var features = await layer.HitTestAsync(MyMapView, e.Position);
				if (features == null || !features.Any())
					return;
				var featureID = features.FirstOrDefault();
				layer.SelectFeatures(new long[] { featureID });
				await QueryAttachmentsAsync(featureID);
			}
			catch (Exception ex)
			{
				message = ex.Message;
			}
			if (!string.IsNullOrWhiteSpace(message))
				MessageBox.Show(message);
		}

		/// <summary>
		/// Prepares attachment editor for editing.
		/// </summary>
		private void SetAttachmentEditor(long featureID = 0, IReadOnlyList<AttachmentInfoItem> attachments = null)
		{
			AddButton.IsEnabled = featureID != 0;
			AttachmentList.Tag = featureID;
			AttachmentList.ItemsSource = attachments;
			AttachmentList.IsEnabled = attachments != null && attachments.Count > 0;
		}

		/// <summary>
		/// Submits attachment edits back to server.
		/// </summary>
		private async Task SaveEditsAsync()
		{
			var layer = MyMapView.Map.Layers["Incidents"] as FeatureLayer;
			var table = (ArcGISFeatureTable)layer.FeatureTable;
			if (table.HasEdits)
			{
				if (table is ServiceFeatureTable)
				{
					var serviceTable = (ServiceFeatureTable)table;
					// Pushes attachment edits back to the server.
					var result = await serviceTable.ApplyAttachmentEditsAsync();
					if (result.UpdateResults == null || result.UpdateResults.Count < 1)
						return;
					var updateResult = result.UpdateResults[0];
					if (updateResult.Error != null)
						throw updateResult.Error;
				}
			}
		}

		/// <summary>
		/// Query attachments of specified feature.
		/// </summary>
		private async Task QueryAttachmentsAsync(long featureID)
		{
			var layer = MyMapView.Map.Layers["Incidents"] as FeatureLayer;
			var table = (ArcGISFeatureTable)layer.FeatureTable;
			var attachments = await table.QueryAttachmentsAsync(featureID);
			if (attachments != null)
				SetAttachmentEditor(featureID, attachments.Infos);
		}

		/// <summary>
		/// Prompts user to pick file from pictures folder.
		/// </summary>
		private FileInfo GetFile()
		{
			var dialog = new OpenFileDialog();
			dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
			dialog.Multiselect = false;
			dialog.Filter = "Image Files|*.tif;*.jpg;*.gif;*.png;*.bmp";
			var dialogResult = dialog.ShowDialog();
			if (dialogResult.HasValue && dialogResult.Value)
				return new FileInfo(dialog.FileName);
			return null;
		}

		/// <summary>
		/// Adds new attachment to feature.
		/// </summary>
		private async void AddButton_Click(object sender, RoutedEventArgs e)
		{
			string message = null;

			try
			{
				var featureID = (Int64)AttachmentList.Tag;
				var layer = MyMapView.Map.Layers["Incidents"] as FeatureLayer;
				var table = (ArcGISFeatureTable)layer.FeatureTable;
				var file = GetFile();
				if (file == null) return;

				AttachmentResult addResult = null;
				using (var stream = file.OpenRead())
				{
					addResult = await table.AddAttachmentAsync(featureID, stream, file.Name);
				}
				if (addResult != null)
				{
					if (addResult.Error != null)
						message = string.Format("Add attachment to feature [{0}] failed.\n {1}", featureID, addResult.Error.Message);
					await SaveEditsAsync();
					await QueryAttachmentsAsync(featureID);
				}
			}
			catch (Exception ex)
			{
				message = ex.Message;
			}
			if (!string.IsNullOrWhiteSpace(message))
				MessageBox.Show(message);
		}

		/// <summary>
		/// Opens the specified attachment.
		/// </summary>
		private async void OpenButton_Click(object sender, RoutedEventArgs e)
		{
			var info = (AttachmentInfoItem)((FrameworkElement)sender).DataContext;
			string message = null;
			try
			{
				using (var data = await info.GetDataAsync())
				{
					if (data != Stream.Null)
					{
						var source = new BitmapImage();
						source.BeginInit();
						source.StreamSource = data;
						source.EndInit();
						var window = new Window();
						window.Content = new Image() { Source = source };
						window.ShowDialog();
					}
				}
			}
			catch (Exception ex)
			{
				message = ex.Message;
			}
		}

		/// <summary>
		/// Updates the specified attachment of feature.
		/// </summary>
		private async void UpdateButton_Click(object sender, RoutedEventArgs e)
		{
			var featureID = (Int64)AttachmentList.Tag;
			var info = (AttachmentInfoItem)((FrameworkElement)sender).DataContext;
			var layer = MyMapView.Map.Layers["Incidents"] as FeatureLayer;
			var table = (ArcGISFeatureTable)layer.FeatureTable;
			var file = GetFile();
			if (file == null) return;
			string message = null;
			try
			{
				AttachmentResult updateResult = null;
				using (var stream = file.OpenRead())
				{
					updateResult = await table.UpdateAttachmentAsync(featureID, info.ID, stream, file.Name);
				}
				if (updateResult != null)
				{
					if (updateResult.Error != null)
						message = string.Format("Update on attachment [{0}] of feature [{1}] failed.\n {2}", info.ID, featureID, updateResult.Error.Message);
					await SaveEditsAsync();
					await QueryAttachmentsAsync(featureID);
				}
			}
			catch (Exception ex)
			{
				message = ex.Message;
			}
			if (!string.IsNullOrWhiteSpace(message))
				MessageBox.Show(message);
		}

		/// <summary>
		/// Deletes the specified attachment from feature.
		/// </summary>
		private async void DeleteButton_Click(object sender, RoutedEventArgs e)
		{
			var featureID = (Int64)AttachmentList.Tag;
			var info = (AttachmentInfoItem)((FrameworkElement)sender).DataContext;
			var layer = MyMapView.Map.Layers["Incidents"] as FeatureLayer;
			var table = (ArcGISFeatureTable)layer.FeatureTable;
			string message = null;
			try
			{
				DeleteAttachmentResult deleteResult = null;
				deleteResult = await table.DeleteAttachmentsAsync(featureID, new long[] { info.ID });
				if (deleteResult != null && deleteResult.Results != null && deleteResult.Results.Count > 0)
				{
					var result = deleteResult.Results[0];
					if (result.Error != null)
						message = string.Format("Delete attachment [{0}] of feature [{1}] failed.\n {2}", info.ID, featureID, result.Error.Message);
					await SaveEditsAsync();
					await QueryAttachmentsAsync(featureID);
				}
			}
			catch (Exception ex)
			{
				message = ex.Message;
			}
			if (!string.IsNullOrWhiteSpace(message))
				MessageBox.Show(message);
		}
	}
}
Feedback on this topic?