FeatureLayer has no graphics collection unless I give it to the Map ...

3068
12
09-09-2012 03:58 AM
Labels (1)
MikeShaw
New Contributor
All,

I have the need to create a FeatureLayer (local or not) and gain access to its Features --without the use of a Map--.  I haven't been successful.  The following steps are what I assumed would work:

1.  Create a LocalFeatureService.
2.  Point it towards a valid MapPackage file.
3.  Start the Service.
4.  On StartCompleted -> Create a LocalFeatureLayer.
5.  Give the LocalFeatureLayer the 'Service' and a valid 'LayerName' (a corresponding, editable layer within the MapPackage).
6.  Initialize the Layer.
7.  OnInitialized -> Call ::Update() on the layer.
8.  Cast to GraphicsLayer.
9.  Get the Graphics Collection.

I assumed I would see all the Features within the Layer as graphics; I don't (its count = 0).

NOTE:  If the LocalFeatureLayer is created and given to a map it will have a valid Graphics Collection.

Does anyone see another way around this??

-Mike
0 Kudos
12 Replies
JustinHunter
New Contributor III
I am also looking for an answer to this. What I am writing is a class library to plug into our in-house CMS application. I need to be able to update features completely through code. Based on what values are passed into me I must see if that specific record already exists in that feature layer. If so, I update it, if not I add it.

Edit: I guess my post shouldn't be in here, since I'm just using ArcObjects that come with Server 10.1, but we'll see!
0 Kudos
AnttiKajanus1
Occasional Contributor III
All,

I have the need to create a FeatureLayer (local or not) and gain access to its Features --without the use of a Map--.  I haven't been successful.  The following steps are what I assumed would work:

1.  Create a LocalFeatureService.
2.  Point it towards a valid MapPackage file.
3.  Start the Service.
4.  On StartCompleted -> Create a LocalFeatureLayer.
5.  Give the LocalFeatureLayer the 'Service' and a valid 'LayerName' (a corresponding, editable layer within the MapPackage).
6.  Initialize the Layer.
7.  OnInitialized -> Call ::Update() on the layer.
8.  Cast to GraphicsLayer.
9.  Get the Graphics Collection.

I assumed I would see all the Features within the Layer as graphics; I don't (its count = 0).

NOTE:  If the LocalFeatureLayer is created and given to a map it will have a valid Graphics Collection.

Does anyone see another way around this??

-Mike


You can use QueryTask to work directly with the map service without the map. I have been using this approach in many cases (well, mainly in Windows Phone projects but nonetheless). I might be a bit old fashioned but I like to work directly with the features when they are the only that I need.

Check ArcGIS Runtime SDK for WPF samples / Search / QueryTask category to give a starting point. Query only is good place to start.
0 Kudos
PatricTrollope
New Contributor
Hi Antti,

Using the query task to query against my feature service, I am able to retrieve a FeatureSet collection that contains all the features that match my query, but from this point I am not able to do anything with them.

My goal is to delete the features returned by my query, but I am not able to get them into a FeatureLayer so that I can edit. If I add the results to a feature layer, and then delete them from the feature layer, no edits are registered, as the feature layer is in the same state as before I started.

Do you have any advice I might try to accomplish my goal of deleting the features from the feature service without first adding them to a map control?

Much appreciated
Patric
0 Kudos
MichaelBranscomb
Esri Frequent Contributor
Hi,

Your workflow is almost right. You can work with FeatureLayers / ArcGISLocalFeatureLayers without adding them to the map. The main difference when not adding the layer to the map is that you should use Snapshot instead of the default mode, OnDemand, which uses the map extent to request features. Snapshot mode gets a snapshot of all features or all available features up to the service imposed limit (determined by the service published when using ArcGIS for Server or you can set this for local feature services). For more info see http://resources.arcgis.com/en/help/runtime-wpf/apiref/index.html?ESRI.ArcGIS.Client~ESRI.ArcGIS.Cli....

It�??s also worth noting the different behaviour of the following methods:

.Update() = Selections and unsaved edits will be lost on Update. Performs a new refreshed query against the service and refreshes the graphics layer.
.SaveEdits() = Save edits to the layer. Only required if AutoSave is false.
.Refresh() = Forces a full redraw of all graphic features but does not affect selections or unsaved edits.


Cheers

Mike
0 Kudos
PatricTrollope
New Contributor
Hi Mike,

Thanks for the feedback, I have tried it but I seem to be getting conflicting information to what you provide.

According to the documentation, the default mode is Snapshot:

http://resources.arcgis.com/en/help/runtime-wpf/apiref/index.html?ESRI.ArcGIS.Client~ESRI.ArcGIS.Cli...

Gets or sets the selection mode. Default is Snapshot mode. If Where is specified, mode becomes Snapshot.


Regardless, I tried to set the query mode explicitly, with the same results - the graphics collection is empty 😞

Below is the code I use to create my feature layer object, perhaps you will see something that I am doing wrong...?

[PHP]
                FeatureLayer myFeatureLayer = new FeatureLayer
                {
                    Url = "http://myserver.com/arcgis/rest/services/myproject/test_service/FeatureServer/0",
                    ID = "TestEdit",
                    Mode = FeatureLayer.QueryMode.Snapshot
                };

                myFeatureLayer.Initialized += new System.EventHandler<System.EventArgs>(myFeatureLayer_Initialized);
                myFeatureLayer.InitializationFailed += new System.EventHandler<System.EventArgs>(myFeatureLayer_InitializationFailed);
                myFeatureLayer.Initialize();
[/PHP]

In my myFeatureLayer_Initialized() method I then cast the sent object to a feature layer and a graphics layer and use a control break to inspect both objects, and the graphics collection is empty...

[PHP]
        void myFeatureLayer_Initialized(object sender, System.EventArgs e)
        {
            var featureLayer = sender as FeatureLayer;
            var graphicsLayer = featureLayer as GraphicsLayer;
            ....
[/PHP]

Once again thanks for taking the time to respond.
Patric
0 Kudos
AnttiKajanus1
Occasional Contributor III
This should work in your case:

      private FeatureLayer myFeatureLayer;

        public MainWindowViewModel()
        {
             myFeatureLayer = new FeatureLayer
            {
                Url = "YourAddRess",
                ID = "TestEdit",
                Mode = FeatureLayer.QueryMode.Snapshot,
            };
 
            myFeatureLayer.Initialized += this.myFeatureLayer_Initialized;
            myFeatureLayer.InitializationFailed += this.myFeatureLayer_InitializationFailed;
            myFeatureLayer.UpdateCompleted += MyFeatureLayerOnUpdateCompleted;
            myFeatureLayer.Initialize();            
        }

        private void MyFeatureLayerOnUpdateCompleted(object sender, EventArgs eventArgs)
        {
            // Magic here.
        }

        private void myFeatureLayer_InitializationFailed(object sender, System.EventArgs e)
        {
        }

         private void myFeatureLayer_Initialized(object sender, System.EventArgs e)
         {
            myFeatureLayer.Update();
         }
 


Edit: Another solution is to use ArcGIS Server Rest API directly within your application but if you go that road, you need to write a lot of code more than in this approach.
0 Kudos
MichaelBranscomb
Esri Frequent Contributor
Hi,

As Antti posted - you need to make sure that after the layer has initialized you're calling the Update() method on the layer and handling the UpdateCompleted event. At that point the layer should be populated with features.

Cheers

Mike
0 Kudos
JustinHunter
New Contributor III
I'm still not having any luck following these examples.

Here's an example of what I'm looking to do:

FeatureLayer layer = new FeatureLayer();
layer.Url = "http://localhost:6080/arcgis/rest/services/QueryMap/FeatureServer/0";
layer.Where = "1=1"; // Hard-coded for now, until we can retrieve results
layer.Mode = FeatureLayer.QueryMode.SelectionOnly;
layer.OutFields = new OutFields() { "*" };
layer.Initialized += FeatureLayer_Initialized;
layer.Initialize();


I have my breakpoint in FeatureLayer_Initialized and everything up until then. I have yet to come across the layer where the graphics count has been > 0 other than when I add the feature directly to my map, which isn't an option in the long run because this is going to be a class library.

I have noted there is a 'SelectedGraphics' but that is also 0.

My work around so far has been to not use the SDK/API tools given to me but instead directly query my REST service through an HttpRequest and parsing the HttpResponse to figure out if that feature exists, and then again use the REST add/update feature necessary, depending on my query results.

Though I've found this somewhat speedier, I'd still like to know a way to do this through the tools given.

Thanks for all the help so far.

Edit: After seeing mbranscomb's post, I added .Update() to the layer in the FeatureLayer_Initialized event handler, but never does my breakpoint hit inside my layer_UpdateCompleted or layer_UpdateCompleted events. Am I not putting the .Update() in the right spot? There is no where that I can see it become IsInitialized=true before my code execution ends.
0 Kudos
AnttiKajanus1
Occasional Contributor III
I'm still not having any luck following these examples.

Here's an example of what I'm looking to do:

FeatureLayer layer = new FeatureLayer();
layer.Url = "http://localhost:6080/arcgis/rest/services/QueryMap/FeatureServer/0";
layer.Where = "1=1"; // Hard-coded for now, until we can retrieve results
layer.Mode = FeatureLayer.QueryMode.SelectionOnly;
layer.OutFields = new OutFields() { "*" };
layer.Initialized += FeatureLayer_Initialized;
layer.Initialize();


I have my breakpoint in FeatureLayer_Initialized and everything up until then. I have yet to come across the layer where the graphics count has been > 0 other than when I add the feature directly to my map, which isn't an option in the long run because this is going to be a class library.

I have noted there is a 'SelectedGraphics' but that is also 0.

My work around so far has been to not use the SDK/API tools given to me but instead directly query my REST service through an HttpRequest and parsing the HttpResponse to figure out if that feature exists, and then again use the REST add/update feature necessary, depending on my query results.

Though I've found this somewhat speedier, I'd still like to know a way to do this through the tools given.

Thanks for all the help so far.


As Mike pointed earlier in this thread, use FeatureLayer.QueryMode.Snapshot as a Mode. You can see how to initialize layer from my previous post.
0 Kudos