ArcGIS Pro SDK - Select Layer regardless if it is in a Group Layer or not.

1177
3
Jump to solution
02-02-2018 11:41 AM
Highlighted

I am trying to create a Map Tool where it only selects features in my "Parcels" layer.  Some users will have the "Parcels" layer inside a Group Layer in the Map and some will not.

.NET C#

var parcellayer = (MapView.Active.Map.Layers.First(layer => layer.Name.Equals("Parcels")) as FeatureLayer);‍‍‍

This works well if the layer is directly in the Map, but will crash if the layer is in a Group Layer in the Map.

I have yet to figure out how to use a layer within a Group Layer in the same manner, simply because it is not what I am after.

According to ProConcepts Map Authoring · Esri/arcgis-pro-sdk Wiki · GitHub , Working with Map Members, one should use FlattenedList because "Should you need to get a list without group layers hierarchy, use Map.GetLayersAsFlattenedList() method". 

When I do this, nothing happens when I try and use the new Map Tool

.NET C#

var parcellayer = (MapView.Active.Map.GetLayersAsFlattenedList().Where(layer => layer.Name.Equals("Parcels")) as FeatureLayer);‍‍‍

I want to be able to make a Select Map Tool where it will select the "Parcels" layer regardless of if it is in a Group Layer or not.

 

To add more confusion.  I can run a stand alone Python Script within Pro and it will not matter if a feature layer is in a Group layer or not.

Python 

selectPar = pm.SelectLayerByLocation("Parcels","WITHIN_A_DISTANCE",ZoneCaseFeat,"1000 Feet","NEW_SELECTION")
‍‍‍‍‍

But if I run this same exact Python script from within .NET I have to put the Group in there first.

Python

selectPar = pm.SelectLayerByLocation(r"GroupLayerName\Parcels","WITHIN_A_DISTANCE",ZoneCaseFeat,"1000 Feet","NEW_SELECTION")‍‍‍

But if I do this and run the Python script from within .Net it will work fine in or out of a group! 

Python

aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Layers")[0]
ParcelsLayer = m.listLayers("Parcels")[0]
selectPar = pm.SelectLayerByLocation(ParcelsLayer,"WITHIN_A_DISTANCE",ZoneCaseFeat,"1000 Feet","NEW_SELECTION")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
1 Solution

Accepted Solutions
Highlighted
New Contributor III

The GetLayersAsFlattenedList is the only way to do that that I know of. The issue seems to be using the .Where() call instead of .First() when you use the flattened list. The compiler doesn't catch it, but the parcellayer object will be null after that, so the empty task gets returned.

View solution in original post

3 Replies
Highlighted

Here is the full code I am trying to get to work.

namespace Parcel_Select
{
internal class SelectParcel : MapTool
{
public SelectParcel()
{
IsSketchTool = true;
SketchType = SketchGeometryType.Rectangle;
SketchOutputMode = SketchOutputMode.Map;
}
protected override Task OnToolActivateAsync(bool active)
{
return base.OnToolActivateAsync(active);
}
protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
{
var parcellayer = (MapView.Active.Map.Layers.First(layer => layer.Name.Equals("Parcels")) as FeatureLayer);
//var parcellayer = (MapView.Active.Map.GetLayersAsFlattenedList().Where(layer => layer.Name.Equals("Parcels")) as FeatureLayer);
if (parcellayer == null) return Task.FromResult(true);
return ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
var sqatialfilter = new SpatialQueryFilter()
{
FilterGeometry = geometry,
SpatialRelationship = SpatialRelationship.Intersects
};
MapView.Active.Map.SetSelection(null);
parcellayer.Select(sqatialfilter);
return base.OnSketchCompleteAsync(geometry);
});

}
}
}
0 Kudos
Highlighted
New Contributor III

The GetLayersAsFlattenedList is the only way to do that that I know of. The issue seems to be using the .Where() call instead of .First() when you use the flattened list. The compiler doesn't catch it, but the parcellayer object will be null after that, so the empty task gets returned.

View solution in original post

Highlighted

Thanks, that was it!  

This is the corrected code.

MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().First(l => l.Name.Equals("Parcels"));
0 Kudos