Select to view content in your preferred language

Insert new feature in a feature service layer via a geocode result.

1708
11
11-03-2011 12:02 PM
MattMiley
Deactivated User
Is there away to insert a new feature in a feature service layer via a geocode result?

There isn't much documentation in the Editing Features section of the Concepts Tab in the ESRI Silverlight API. I would just like to take away the need for the user to pick a geographical point on the map to make a new feature and instead just have the feature's coordinates be determined by a geocode result.

Any suggestions on how to achieve this would be greatly appreciated.
0 Kudos
11 Replies
PreetiMaske
Esri Regular Contributor
Please take a look at sample
http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#LocationToAddress

All you need to do is tweak the sample a little bit for adding the returned result of the geocoding to a featureservice.
In the codebehind go to in LocatorTask_LocationToAddressCompleted. In this event instead of adding the graphic to the graphic layer, you can add the graphic to your FeatureService(editable FeatureLayer) and call FeatureLayer.SaveEdits() to save the results.

Hope this helps!
0 Kudos
MattMiley
Deactivated User
Well I managed to get it to create a new feature from a geocode result, But now i can't add attributes to the new feature. I add attributes of the newly created feature in a featuregrid but it won't save. I have to refresh the page atleast once then edit the attributes before it lets me add attributes and save.
How do you update, refresh, and save attributes of the feature layer in code?

using System;

namespace GeoEdit
{
    public partial class MainPage : UserControl
    {
        Locator _locatorTask;
        GraphicsLayer _candidateGraphicsLayer;
        private static ESRI.ArcGIS.Client.Projection.WebMercator _mercator =
            new ESRI.ArcGIS.Client.Projection.WebMercator();

        public MainPage()
        {
            InitializeComponent();

            ESRI.ArcGIS.Client.Geometry.Envelope initialExtent =
                    new ESRI.ArcGIS.Client.Geometry.Envelope(
                _mercator.FromGeographic(
                    new ESRI.ArcGIS.Client.Geometry.MapPoint(-82.23, 41.48)) as MapPoint,
                _mercator.FromGeographic(
                    new ESRI.ArcGIS.Client.Geometry.MapPoint(-82.15, 41.4)) as MapPoint);

            initialExtent.SpatialReference = new SpatialReference(102100);

            MyMap.Extent = initialExtent;

            _candidateGraphicsLayer = MyMap.Layers["PointLayer"] as GraphicsLayer;
        }

        private void FindAddressButton_Click(object sender, RoutedEventArgs e)
        {
            _locatorTask = new Locator("http://tasks.arcgisonline.com/ArcGIS/rest/services/Locators/TA_Streets_US_10/GeocodeServer");
            _locatorTask.AddressToLocationsCompleted += LocatorTask_AddressToLocationsCompleted;
            _locatorTask.Failed += LocatorTask_Failed;

            AddressToLocationsParameters addressParams = new AddressToLocationsParameters()
            {
                OutSpatialReference = MyMap.SpatialReference
            };

            Dictionary<string, string> address = addressParams.Address;

            if (!string.IsNullOrEmpty(InputAddress.Text))
                address.Add("Street", InputAddress.Text);
            if (!string.IsNullOrEmpty(City.Text))
                address.Add("City", City.Text);
            if (!string.IsNullOrEmpty(State.Text))
                address.Add("State", State.Text);
            if (!string.IsNullOrEmpty(Zip.Text))
                address.Add("ZIP", Zip.Text);

            _locatorTask.AddressToLocationsAsync(addressParams);
        }

        private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
        {

            CandidateListBox.Items.Clear();

            List<AddressCandidate> returnedCandidates = args.Results;

            foreach (AddressCandidate candidate in returnedCandidates)
            {
                if (candidate.Score >= 80)
                {
                    CandidateListBox.Items.Add(candidate.Address);

                    Graphic graphic = new Graphic()
                    {
                        Symbol = LayoutRoot.Resources["DefaultMarkerSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol,
                        Geometry = candidate.Location
                    };

                    graphic.Attributes.Add("Address", candidate.Address);

                    string latlon = String.Format("{0}, {1}", candidate.Location.X, candidate.Location.Y);
                    graphic.Attributes.Add("LatLon", latlon);

                    if (candidate.Location.SpatialReference == null)
                    {
                        candidate.Location.SpatialReference = new SpatialReference(4326);
                    }

                    if (!candidate.Location.SpatialReference.Equals(MyMap.SpatialReference))
                    {
                        if (MyMap.SpatialReference.Equals(new SpatialReference(102100)) && candidate.Location.SpatialReference.Equals(new SpatialReference(4326)))
                            graphic.Geometry = _mercator.FromGeographic(graphic.Geometry);
                        else if (MyMap.SpatialReference.Equals(new SpatialReference(4326)) && candidate.Location.SpatialReference.Equals(new SpatialReference(102100)))
                            graphic.Geometry = _mercator.ToGeographic(graphic.Geometry);
                        else if (MyMap.SpatialReference != new SpatialReference(4326))
                        {
                            GeometryService geometryService =
                                new GeometryService("http://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

                            geometryService.ProjectCompleted += (s, a) =>
                            {
                                graphic.Geometry = a.Results[0].Geometry;
                            };

                            geometryService.Failed += (s, a) =>
                            {
                                MessageBox.Show("Projection error: " + a.Error.Message);
                            };

                            geometryService.ProjectAsync(new List<Graphic> { graphic }, MyMap.SpatialReference);
                        }
                    }

                    _candidateGraphicsLayer.Graphics.Add(graphic);
                }
            }

            if (_candidateGraphicsLayer.Graphics.Count > 0)
            {
                CandidatePanelGrid.Visibility = Visibility.Visible;
                CandidateListBox.SelectedIndex = 0;
            }
        }

        void _candidateListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            int index = (sender as ListBox).SelectedIndex;
            if (index >= 0)
            {
                MapPoint candidatePoint = _candidateGraphicsLayer.Graphics[index].Geometry as MapPoint;
                double displaySize = MyMap.MinimumResolution * 30;

                ESRI.ArcGIS.Client.Geometry.Envelope displayExtent = new ESRI.ArcGIS.Client.Geometry.Envelope(
                    candidatePoint.X - (displaySize / 2),
                    candidatePoint.Y - (displaySize / 2),
                    candidatePoint.X + (displaySize / 2),
                    candidatePoint.Y + (displaySize / 2));

                MyMap.ZoomTo(displayExtent);
            }
        }

        private void LocatorTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Locator service failed: " + e.Error);
        }

        private void FeatureLayer_MouseLeftButtonUp(object sender, GraphicMouseButtonEventArgs args)
        {
            FeatureLayer featureLayer = sender as FeatureLayer;

            for (int i = 0; i < featureLayer.SelectionCount; i++)
                featureLayer.SelectedGraphics.ToList().UnSelect();

            args.Graphic.Select();
            MyFeatureDataForm.GraphicSource = args.Graphic;

            FeatureDataFormBorder.Visibility = Visibility.Visible;
        }

        private void EditorWidget_Loaded(object sender, RoutedEventArgs e)
        {
            string[] myLayerIDs = { "PointLayer" };
            MyEditorWidget.LayerIDs = myLayerIDs;
        }
    }
}
0 Kudos
MattMiley
Deactivated User
Still having trouble with this, its really weird, it won't let me add and save attributes unless i refresh the page and click or change other features first.
0 Kudos
JenniferNery
Esri Regular Contributor
You can do the following:
* set Geometry with LocatorTask result.
* set Attributes with default value, you might need to check FieldType, Editable, Nullable, etc.
* add to FeatureLayer before using FeatureDataForm/FeatureDataGrid
var g = new Graphic();
g.Geometry = geocodeResult;
foreach (var f in l.LayerInfo.Fields)
 g.Attributes[f.Name] = null;
l.Graphics.Add(g);
var childWindow = new ChildWindow();
var fdf = new FeatureDataForm() { FeatureLayer = l, GraphicSource = g };     
childWindow.Content = fdf;
childWindow.Show();
0 Kudos
MattMiley
Deactivated User

var g = new Graphic();
g.Geometry = geocodeResult;
foreach (var f in l.LayerInfo.Fields)
 g.Attributes[f.Name] = null;
l.Graphics.Add(g);
var childWindow = new ChildWindow();
var fdf = new FeatureDataForm() { FeatureLayer = l, GraphicSource = g };     
childWindow.Content = fdf;
childWindow.Show();


Thanks Jennifer

You're the best, everything worked great except for when i hit the okay button on the FeatureDataForm dialog box it won't close. It only closes if you hit the X to close, The added attributes work though so I'm happy.

I was able to add the following code to get the date down to the minute instead of just the day as well..
 g.Attributes["Date"] = DateTime.Now;
g.Attributes["Job_Location"] = InputAddress.Text;
0 Kudos
JenniferNery
Esri Regular Contributor
If you want the OK button to close your window, you can do this:

        var fdf = new FeatureDataForm() { FeatureLayer = layer, GraphicSource = graphic};
        var window = new ChildWindow() { Content = fdf };
        fdf.EditEnded += (a, b) =>
            {
                window.Close();
            };
        window.Show();
0 Kudos
MattMiley
Deactivated User
How would i auto insert a coded domain

ex     Coded Values: [1: Broken Main], [2: Broken Valve], [3: Broken T Handle]

I tried
 //g.Attributes["Job_Type"] = "2";
 //g.Attributes["Job_Type"] = "'2'";
 //g.Attributes["Job_Type"] = "Broken Valve";
 //g.Attributes["Job_Type"] = "'Broken Valve'";


and it still can't get it to auto populated the drop menu.
0 Kudos
JenniferNery
Esri Regular Contributor
It depends on your service. For example, this service defines its coded value domain as:
STATUS ( type: esriFieldTypeSmallInteger , alias: Status , editable: true , nullable: true ,   Coded Values: [1: New] , [2: Open] , [3: Closed] )

This feature attribute will then be:
graphic.Attributes["STATUS"] = 1;

where datatype is Int16 and is one of the possible code 1, 2, 3.
http://servicesbeta2.esri.com/arcgis/rest/services/SF311/FeatureServer/0/1
0 Kudos
MattMiley
Deactivated User
It depends on your service. For example, this service defines its coded value domain as:

This feature attribute will then be:
graphic.Attributes["STATUS"] = 1;

where datatype is Int16 and is one of the possible code 1, 2, 3.
http://servicesbeta2.esri.com/arcgis/rest/services/SF311/FeatureServer/0/1


Hmm, Still not working, does it matter if that field is used as a Unique Value Renderer?

[HTML]Drawing Info:

    Renderer:
        Unique Value Renderer:

        Field 1: Job_Type
        Field 2:
        Field 3:
        Field Delimiter: ,
        Default Symbol:
            Unsupported Symbol
        Default Label:
        Unique Value Infos:
            Value: 1
            Label: Broken Main
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 3
            Label: Broken T Handle
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 2
            Label: Broken Valve
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 6
            Label: Dirty Water
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 4
            Label: Hydrant Flush
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 9
            Label: Hydrant Repair
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 10
            Label: Hydrant Replacement
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 5
            Label: Leak
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 11
            Label: New Water Taps
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 7
            Label: Other
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 12
            Label: Replacement Water Service
            Description:
            Symbol:
                Picture Marker Symbol:

            Value: 8
            Label: Valve Turn
            Description:
            Symbol:
                Picture Marker Symbol:

    Transparency: 0
    Labeling Info: N/A

Has Attachments: False

HTML Popup Type: esriServerHTMLPopupTypeAsHTMLText

Object ID Field: OBJECTID

Global ID Field:

Type ID Field: Job_Type

Fields:

    OBJECTID (Type: esriFieldTypeOID, Alias: OBJECTID, Editable: False)
    Job_Type (Type: esriFieldTypeSmallInteger, Alias: Job Type, Editable: True, Domain: Coded Values: [1: Broken Main], [2: Broken Valve], [3: Broken T Handle], ...9 more...)[/HTML]

This didn't work
 g.Attributes["Job_Type"] = 1;


Also the field isn't nullable.
0 Kudos