Is there a way to loop through the TOC and preserve the nested hierarchy i.e. NOT the GetLayersAsFlattenedList() method. I also need to examine whether they are group layers or feature/raster layers as I go round.
Can't find anything obvious. I did try:
MapView.Active.Map.Layers
but that just returned me the project node, an item count of 1 - when I had numerous layers loaded in, that made no sense to me.
If anyone can help that would be great.
Hi
You can iterate through the layers in the TOC and determine if a layer is a Group layer or not using the "GroupLayer" type.
var map = MapView.Active.Map;
if (map == null)
return;
//Get the group layers first
IReadOnlyList<GroupLayer> groupLayers = map.Layers.OfType<GroupLayer>().ToList();
//Iterate
foreach (var groupLayer in groupLayers)
{
//Do something with groupLayer
}
There is a snippet in the ProSDK wiki that iterates through the TOC. In this snippet, unchecked layers are removed from the TOC. Removes all layers that are unchecked
Uma's suggestion works only for group layers, if you want a more general way to traverse the layer hierarchy you have to use the Layers collection of the Map class, as suggest by Uma. But when you iterate through the layers you need to look at the real type of the layer object (in essence each class that derives from the Layer class) and if the derived type has a Layers collection you then iterate into that sub layer collection. Below is a sample implementation, however, the implementation is incomplete because it only looks at AnnotationLayers and CompositeLayers as 2nd level entries in the TOC (there are more classes the derive from the Layer class and that have a Layers collection).
protected override void OnClick()
{
try
{
var mva = MapView.Active;
if (mva == null) return;
var layers = mva.Map.Layers;
StringBuilder sb = new();
GetLayers(layers, sb, "");
MessageBox.Show(sb.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private static bool GetLayers(ReadOnlyObservableCollection<Layer> layers, StringBuilder sb, string indent)
{
foreach (var layer in layers)
{
var lyrName = layer.Name.Substring(0, Math.Min(40, layer.Name.Length));
sb.AppendLine($@"{indent}{lyrName} {layer.GetType().Name}");
if (layer is AnnotationLayer annoLyr)
{
GetLayers(annoLyr.Layers, sb, indent + " ");
continue;
}
if (layer is CompositeLayer compositeLyr)
{
GetLayers(compositeLyr.Layers, sb, indent + " ");
continue;
}
}
return true;
}