Hi,
I am trying to filter an IEnumLayer to only contain visible layers. I want to pass this to IFeatureCache2.AddLayers(...). I could not find any public implementations of IEnumLayer. Since we are in C# I wrote a couple of extension methods that convert IEnumLayer to IEnumerable<ILayer> and vice-versa. But passing my custom implementation of IEnumLayer did not seem to make AddLayers(...) happy.
Here is my extensions class:
public static class EnumLayerExtensions { public static IEnumerable<ILayer> AsEnumerable(this IEnumLayer layers) { layers.Reset(); var layer = layers.Next(); while (layer != null) { yield return layer; layer = layers.Next(); } } public static IEnumLayer ToEnumLayer(this IEnumerable<ILayer> layers) { return new EnumLayerWrapper(layers); } private class EnumLayerWrapper : IEnumLayer { private readonly ILayer[] _layers; private int _index; public EnumLayerWrapper(IEnumerable<ILayer> layers) { _layers = layers.ToArray(); _index = 0; } public ILayer Next() { return _index < _layers.Length ? _layers[_index++] : null; } public void Reset() { _index = 0; } } }
using this I can then write the following code:
var visibleLayers = Map.Layers.AsEnumerable().Where(l=>l.Visible); var cache = new FeatureCacheClass() as IFeatureCache2; cache.Initialize(point,radius); cache.AddLayers(visibleLayers.ToEnumLayer(), null);
In the above code, line 04 will just run for ever as-is. If I use the layers straight from the Map, it comes back fairly fast. I have written a handful of unit tests to validate my implementation of ToEnumLayer() and they all seem to pass. Based on all this, I have a couple of questions:
Thanks in advance for any help,
Eric.
Solved! Go to Solution.
Eric,
You'll probably find its looping through the ILayer Next implementation.
You'll need to throw an exception there rather than return null.
public ILayer Next()
{
if (index < layers.Count)
return layers[index++];
else
throw new Exception();
}
Hi
There is no way to create IEnumLauers only to get it from IMap.Layers
If you need only the visible layers run a loop on the layers (from bottom up) and IMap.DeleteLayer all the non-visible layers and then use IMap.Layers.
Then you can exists without save or keep a list of the deleted layers and add them back to the map.
Have Fun
Mody
Eric,
At a glance, your extension methods and wrapper class implementing IEnumLayer look good. The problem may be in the way that the IFeatureCache object is interacting with the structure you've created.
Have you instrumented the methods of your wrapper class (e.g. Debug.WriteLine) to see what happens after calling cache.AddLayers?
Eric,
You'll probably find its looping through the ILayer Next implementation.
You'll need to throw an exception there rather than return null.
public ILayer Next()
{
if (index < layers.Count)
return layers[index++];
else
throw new Exception();
}
Sean,
Thanks for the info. It all sounded too familiar when Rich Ruh contacted me yesterday to see if that would work. It does actually work. Now, my custom IEnumLayer implementation does work.
However, my first experiments are not looking too promising the IFeatureCache2 respecting layers. It seems that it goes straight to the FeatureClass, ignoring the definition query.
Eric,
You're right. I took a look at the source and despite the name, AddLayers is adding the underlying featureclass to the cache rather than the display layer, so it wont respect the definition query. I'll add a CR....
Eric,
Giving credit where credit is due, Sean Jones provided the answer to me when I contacted you yesterday.
--Rich