Select to view content in your preferred language

How do you serialize the selection state of Features in a FeatureLayer?

61
2
Jump to solution
Thursday
Labels (3)
JBuchanan
Emerging Contributor

We may be entirely going about this the wrong way, but we currently store the 'state' of the FeatureLayer by storing several of its properties on a wrapper class and then serializing that class. So, for FeatureLayers we store the data path, name, renderer json, labelling info, and definition expression as just strings/bools. On deserialization we create a new layer from the path and set all those stored properties back on the layer. One thing that is missing from our setup is the selection state for features.

One idea we had was to:

  1. Get selected features (featureLayer.GetSelectedFeaturesAsync())
  2. Determine the ID field for that feature table.
    1. If it's an ArcGISFeatureTable, then you can use the GlobalIDField property.
    2. If it's a ShapeFileFeatureTable, then it should always be "FID"?
    3. Unsure what to do if its GeoPackageFeatureTable.
  3. For each selected feature get the ID value from its attribute table using the ID field from step 2.
  4. Serialize this collection of string IDs alongside the other layer info.
  5. On deserialization build a QueryParameter with a where clause with something like $"Where {tableIDFromStep2} IN ({string.Join(", ", selectedFeatureIDs})"
  6. Query out those features and select them on the newly loaded layer.

The concerns for this setup are pretty minor, but worth mentioning:

  1. Are we identifying the correct field ID? The users are bringing in their own data sources, so can we be certain we are always getting the right key?
  2. We could end up storing/querying 100k+ features for large datasets if the user decides to select the whole map for some reason which could be costly and bloat the json file.

 

So, with that said, is this the intended way of doing this? Or is there a much simpler option I missed?

0 Kudos
1 Solution

Accepted Solutions
JenniferNery
Esri Regular Contributor

I think your overall approach is reasonable, but you may be able to simplify it.

Rather than special-casing ArcGISFeatureTable, shapefiles, GeoPackages, etc., you can determine the ObjectID field from the table schema, then serialize the ObjectIDs of the selected features:

 
var objectIdField = featureTable.Fields.FirstOrDefault(f => f.FieldType == FieldType.OID);
long objectId = Convert.ToInt64(feature.GetAttributeValue(objectIdField.Name));
 
 
To restore the selection, you could persist a mapping of FeatureTable.TableName (assuming it is unique in your application) to a list of selected ObjectIDs obtained from FeatureLayer.GetSelectedFeaturesAsync(). On reload, populate QueryParameters.ObjectIds with the saved IDs, query the matching features, and select them on the layer.

 

This has a couple of advantages:

  • You don't need to know the specific FeatureTable implementation to identify the key field.
  • You can use QueryParameters.ObjectIds directly rather than constructing a potentially large WHERE ... IN (...) clause.

Regarding the concern about large selections (100k+ features), any solution will need to persist enough information to identify those selected features. Storing ObjectIDs is about as compact as you can get, but the amount of data you save and restore will still scale with the size of the selection.

 

View solution in original post

2 Replies
JenniferNery
Esri Regular Contributor

I think your overall approach is reasonable, but you may be able to simplify it.

Rather than special-casing ArcGISFeatureTable, shapefiles, GeoPackages, etc., you can determine the ObjectID field from the table schema, then serialize the ObjectIDs of the selected features:

 
var objectIdField = featureTable.Fields.FirstOrDefault(f => f.FieldType == FieldType.OID);
long objectId = Convert.ToInt64(feature.GetAttributeValue(objectIdField.Name));
 
 
To restore the selection, you could persist a mapping of FeatureTable.TableName (assuming it is unique in your application) to a list of selected ObjectIDs obtained from FeatureLayer.GetSelectedFeaturesAsync(). On reload, populate QueryParameters.ObjectIds with the saved IDs, query the matching features, and select them on the layer.

 

This has a couple of advantages:

  • You don't need to know the specific FeatureTable implementation to identify the key field.
  • You can use QueryParameters.ObjectIds directly rather than constructing a potentially large WHERE ... IN (...) clause.

Regarding the concern about large selections (100k+ features), any solution will need to persist enough information to identify those selected features. Storing ObjectIDs is about as compact as you can get, but the amount of data you save and restore will still scale with the size of the selection.

 

JBuchanan
Emerging Contributor

Thanks Jennifer, that is exactly what I was looking for!

0 Kudos