[GIS] Casting ILayer to IFeatureLayer in ArcObjects

arcgis-10.1arcmaparcobjectsc

I'm trying to use the following code in an ArcMap 10.1 extension:

    private IFeatureLayer getLayer(string lname)
    {
        IMap          map;
        IFeatureLayer flayer;
        IEnumLayer    layerTag;
        ILayer        layer;

        try
        {
            map = ArcMap.Document.FocusMap;
            layerTag = map.Layers;
            layer = layerTag.Next();
            while (layer != null)
            {

                flayer = (IFeatureLayer) layer;

                if (flayer.Name.Equals(lname))
                {
                    if(validateFeatureClass(flayer.FeatureClass)){
                        flayer.Visible = true;
                        flayer.Selectable = true;
                        return flayer;
                    }
                }
                layer = layerTag.Next();
            }
            return null;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            return null;
        }
    }

but it hits the skids (throws a cast exception) when I try to use flayer = (IFeatureLayer) layer;

I had before flayer = layer as IFeatureLayer but then name checking line failed due to a null reference exception.

Am I missing something obvious here?

Best Answer

IMap.Layers returns an enumerator over all layers in the map document. This includes group, raster, vector, graphics layers, and non-root layers in the TOC (i.e. it recurses into group layers). If you have any non feature layers in the map document, casting the ILayer to IFeatureLayer will throw an exception. To handle this, either do a dynamic cast and null check to skip non feature layers:

flayer = layer as IFeatureLayer;
if(layer == null)
{
    layer = layers.Next();
    continue;
}

Alternatively, fetch only the IFeatureLayers from the document:

private IFeatureLayer getLayer(string lname)
{
    IMap          map;
    IFeatureLayer flayer;
    IEnumLayer    layerTag;
    ILayer        layer;

    try
    {
        map = ArcMap.Document.FocusMap;

        //Create a UID for IFeatureLayer's interface ID
        UID uid = new UIDClass();
        uid.Value = "{" + typeof(IFeatureLayer).GUID.ToString() + "}";
        //Only fetch layers that implement that interface
        layerTag = map.get_Layers(uid);

        layer = layerTag.Next();
        while (layer != null)
        {

            flayer = (IFeatureLayer) layer;

            if (flayer.Name.Equals(lname))
            {
                if(validateFeatureClass(flayer.FeatureClass)){
                    flayer.Visible = true;
                    flayer.Selectable = true;
                    return flayer;
                }
            }
            layer = layerTag.Next();
        }
        return null;
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error: " + ex.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        return null;
    }
}
Related Question