Editing Tables in Feature Service with Silverlight 4

7408
38
01-21-2011 08:34 AM
by Anonymous User
Not applicable
I fielded a question this week that may help other Silverlight 4 developers working with Esri products.  The question was how to add records to a table that lives inside a geodatabase.  While there is probably more then one way to skin this cat, here is one way to do this if you've got the Silverlight Toolkit installed.

In short, I used the Feature Service. If other people have a different implementation feel free to share.





<UserControl x:Class="StandaloneTableEditing.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
    xmlns:df="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

   �??- note the SL toolkit package is used here �?� 

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid x:Name="MyForm">
            <Grid.RowDefinitions>
                <RowDefinition Height="40" ></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <TextBlock Text="Silverlight Standalone Table Editing" Margin="10" FontSize="14" >
            </TextBlock>
            <df:DataForm x:Name="myDataForm" AutoEdit="False" CommandButtonsVisibility="All" Grid.Row="1" Width="400" Height="300" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top" >
            </df:DataForm>
        </Grid>

    </Grid>

</UserControl>





using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client;
using System.ComponentModel;

//Check to aake sure the System.ComponentModel reference has been added

namespace StandaloneTableEditing
{
    public partial class MainPage : UserControl
    {
        public string Owner { get; set; }
        public int Value { get; set; }
        public string Approved { get; set; }
        public int Lastupdate { get; set; }
        public Inspection inspection { get; set; }
        public FeatureLayer featurelayer { get; set; }

        public MainPage()
        {
            InitializeComponent();
            InitializeFeatureService();
            InitializeInspection();
            myDataForm.CurrentItem = inspection;  // Set up data form with data using the set Inspection Class below
        }


        private void InitializeInspection()
        {
            //Set up default values
            inspection = new Inspection()
            {
                Owner = "David Hasselhoff ",
                Value = 100,
                Approved = "Bay Watch",
                Lastupdate = 1111,
                InspectionFeatureLayer = featurelayer
            };
        }

        public void InitializeFeatureService()
        {
            featurelayer = new FeatureLayer();
            featurelayer.Url = "http://serverbox/ArcGIS/rest/services/EditingTables/FeatureServer/1";
            featurelayer.AutoSave = false;
            featurelayer.Mode = FeatureLayer.QueryMode.OnDemand;
            featurelayer.Initialized += Table_IsInitialized;
            featurelayer.Initialize();
            featurelayer.EndSaveEdits += Insert_EndSaveEdits;
            featurelayer.SaveEditsFailed += Insert_SaveEditsFailed;

        }

        public void Table_IsInitialized(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("it's initialized...");
        }

        public void Insert_SaveEditsFailed(object sender, EventArgs e)
        {
            string mes = e.ToString();  // For debugging
            System.Diagnostics.Debug.WriteLine(mes);
        }

        public void Insert_EndSaveEdits(object sender, EventArgs e)
        {
            string mes = e.ToString(); // For debugging
            System.Diagnostics.Debug.WriteLine(mes);
        }

    }

    public class Inspection : IEditableObject
    {
        public string Owner { get; set; }
        public int Value { get; set; }
        public string Approved { get; set; }
        public int Lastupdate { get; set; }
        public Inspection TempInspection { get; set; }
        public FeatureLayer InspectionFeatureLayer;

        public void BeginEdit()
        {
            // Save current Values
            TempInspection = new Inspection()
            {
                Owner = this.Owner,
                Value = this.Value,
                Approved = this.Approved,
                Lastupdate = this.Lastupdate
            };
        }

        public void CancelEdit()
        {
            // Reset Values
            Owner = TempInspection.Owner;
            Value = TempInspection.Value;
            Approved = TempInspection.Approved;
            Lastupdate = TempInspection.Lastupdate;
        }

        public void EndEdit()
        {

            ESRI.ArcGIS.Client.Graphic graphicAttribute = new ESRI.ArcGIS.Client.Graphic();
            graphicAttribute.Attributes.Add("OWNER", this.Owner);
            graphicAttribute.Attributes.Add("VALUE", this.Value);
            graphicAttribute.Attributes.Add("APPROVED", this.Approved);
            graphicAttribute.Attributes.Add("LASTUPDATE", this.Lastupdate);
            InspectionFeatureLayer.Graphics.Add(graphicAttribute);
            InspectionFeatureLayer.SaveEdits();

        }


    }


}





Regards,
Doug Carroll, ESRI Support Services SDK Team
http://support.esri.com/
0 Kudos
38 Replies
JenniferNery
Esri Regular Contributor
Thank you for sharing.

Alternatively, you can use FeatureDataForm with Silverlight Toolkit Data Pager. FeatureDataForm adjusts its field container based on the field type. For example, a coded-value domain will use ComboBox instead of TextBox, a DateTime will use DateTimePicker. Attribute values are also converted to their corresponding type. Validation and saving edits are handled by the FeatureDataForm.
0 Kudos
KirkKuykendall
Occasional Contributor III
Is there any way to get the FeatureDataForm to use a combobox for fields that don't use using coded value domains?
0 Kudos
JenniferNery
Esri Regular Contributor
No, FeatureDataForm determines the control it needs to use based on the layer's field type http://help.arcgis.com/en/webapi/silverlight/apiref/ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Field_memb.... ComboBox is only used for CodedValueDomain.
0 Kudos
JennyPalomino
New Contributor
Thank you very much for sharing!  It is perfect for what I need to do.  Just wanted to let you know that new Silverlight API users like me appreciate this.
0 Kudos
CraigPerreault
New Contributor II
Adding a record works great but how do I edit a record in my table?
0 Kudos
JenniferNery
Esri Regular Contributor
You would edit a record the same way, where the record is represented as graphic.
You can probably use FeatureDataGrid or maybe Linq query to identify the graphic (record) with the specific ID and then update its attribute values.
0 Kudos
CraigPerreault
New Contributor II
Jennifer thanks for helping me edit attributes of an existing feature. My code looks like this.

                foreach (KeyValuePair<string, object> aItem in feature.Attributes)
                {
                    if ((aItem.Key == "GLOBALID") && (theGlobalID == Convert.ToString(aItem.Value)))
                    {
                        Graphic myGraphic = new Graphic();
                        myGraphic.Attributes.Add("DATE_LAST_UPDATED", DateTime.Now);
                        featureLayer.Graphics.Add(myGraphic);
                        featureLayer.Update();
                        return;
                    }
                }


Maybe I would not use .ADD when the feature already exists?
featureLayer.Graphics.Add(myGraphic);
0 Kudos
GüntherGrill
New Contributor III
You would edit a record the same way, where the record is represented as graphic.
You can probably use FeatureDataGrid or maybe Linq query to identify the graphic (record) with the specific ID and then update its attribute values.


Hi Jennifer,

I am having difficulties implementing this (just like crperrea had). I am initiating a FeatureLayer (just like in the example above, from a table). At this point the Graphic collection of the Feature Layer is empty, so I tried to query the FeatureService, update its attributes, then add the graphic to the Feature Layer, and save. However BeginEdit is never fired and nothing happens.

       private void QueryTaskExecuteCompletedAttributeQuery(object sender, QueryEventArgs e)
        {
            try
            {
                InitializeFeatureService(); 
                foreach (Graphic graphics in e.FeatureSet.Features)
                {
                    _featurelayer.Graphics.Add(graphics);
                    _featurelayer.Graphics[0].Attributes["PRESENCE"] = Convert.ToInt16(2);
                    _featurelayer.SaveEdits(); 
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
                MessageBox.Show("Error: " + ex.StackTrace);
            }
            
        }


I have read http://forums.arcgis.com/threads/32607-Cant-remove-graphic-from-FeatureLayer-in-code.?p=109837&viewf... :
The graphic you get from a QueryTask is not the same instance as the graphics in the FeatureLayer.
but since my FeatureLayer has no graphics initially, there is nothing to query on in the instance of the featureLayer.

What am I missing here?

Thanks,
Günther
0 Kudos
AjaySisodia2
New Contributor
Thank you for sharing.

Alternatively, you can use FeatureDataForm with Silverlight Toolkit Data Pager. FeatureDataForm adjusts its field container based on the field type. For example, a coded-value domain will use ComboBox instead of TextBox, a DateTime will use DateTimePicker. Attribute values are also converted to their corresponding type. Validation and saving edits are handled by the FeatureDataForm.


Hi Jennifer:

The FeatureDataForm takes GraphicSource as data hook up to extract attributes, and also internally checks if Graphic is coming from the same FeatureLayer, i.e.
private bool CheckGraphicParent()
  {
   if (this.FeatureLayer != null && this.GraphicSource != null)
    return this.FeatureLayer.Graphics.Contains(this.GraphicSource);

   return false;
  }
I tried creating empty graphic and assign table attributes and pass that as GraphicSource so i can use the FeatureDataForm functionalities but it fails.

Could you please provide some code sample to do that?

Also, is there a way to update attributes in the FeatureLayer behind the scene (like timestamp, user auditing) something like running the update query.

Your response will be greatly appreciated.

cheers!
0 Kudos