ArcObjects features not in featuredataset

2715
3
09-22-2015 02:20 PM
StacyMcNeil
New Contributor II

I am trying to loop through layers in a map and return the name of the feature dataset.  I will then be performing some task on features in a specific feature dataset.  My map however is complex and includes some layers that do not reside in a feature dataset.  My code errors at this point.  I would like to somehow step over these layers without error.  The line If pFeatureLayer.DataSourceType = "SDE Feature Class" is an attempt to limit my results since all of those layers reside in a feature dataset but that doesn't seem to be working.  I am new to ArcObject so any help would be greatly appreciated!

Here is my code:

            Dim pMapDocument As IMapDocument = New MapDocument()
            If pMapDocument.IsMapDocument(destfile) Then
                pMapDocument.Open(destfile, Nothing)
                Dim pMap As IMap
                Dim i As Integer
                For i = 0 To pMapDocument.MapCount - 1 Step 1 + 1
                    pMap = pMapDocument.Map(i)
                    MsgBox(pMapDocument.DocumentFilename)
                    Dim pEnumLayer As IEnumLayer
                    Dim pID As New UID
                    Dim pFeatureClass As IFeatureClass
                    Dim pDataset As IDataset
                    Dim pFeatureLayer As IFeatureLayer2
                    pID.Value = "{6CA416B1-E160-11D2-9F4E-00C04F6BC78E}"
                    pEnumLayer = pMap.Layers(pID, True)
                    pEnumLayer.Reset()
                    pFeatureLayer = CType(pEnumLayer.Next, IFeatureLayer2)
                    Do Until pFeatureLayer Is Nothing
                        If pFeatureLayer.DataSourceType = "SDE Feature Class" Then
                            pFeatureClass = pFeatureLayer.FeatureClass
                            pDataset = pFeatureClass.FeatureDataset
                            MsgBox(pDataset.Name)
                        End If
                        pFeatureLayer = CType(pEnumLayer.Next, IFeatureLayer2)
                    Loop
                Next i
            End If
        Next
0 Kudos
3 Replies
FreddieGibson
Occasional Contributor III

You should be able to check if cast the layer to IFeatureLayer and then check if the FeatureLayer.FeatureClass.FeatureDataset is equal to null. If it is null then the dataset is not within a feature dataset.

I would assume that your code would fail on the call the pDataset.Name when the dataset is not within a feature dataset because the call to pFeatureClass.FeatureDataset will be null. Below is the code I used to confirm along with a sample that will display this for you.

using System.Collections.Generic;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using System;
using System.IO;
using System.Reflection;


namespace ListFeatureDatasets

    class Program
    {
        private static readonly LicenseInitializer m_aoInit = new LicenseInitializer();


        private static readonly String m_srcPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        private static readonly String m_mxdPath = Path.Combine(m_srcPath, @"data\SanDiego.mxd");
    
        [STAThread()]
        static void Main(string[] args)
        {
            //ESRI License Initializer generated code.
            m_aoInit.InitializeApplication(new [] { esriLicenseProductCode.esriLicenseProductCodeAdvanced }, new esriLicenseExtensionCode[] { });


            var mxd = new MapDocumentClass();
            mxd.Open(m_mxdPath);


            Dictionary<string, List<string>> results = new Dictionary<string, List<string>>();


            for (int i = 0; i < mxd.MapCount; i++)
            {
                var map = mxd.Map;
                var uid = new UIDClass {Value = "{40A9E885-5533-11D0-98BE-00805F7CED21}"}; // IFeatureLayer


                var enumLayer = map.Layers[uid, true];
                enumLayer.Reset();


                ILayer layer;


                while ( (layer = enumLayer.Next()) != null)
                {
                    var fc = (layer as IFeatureLayer).FeatureClass;


                    if (fc.FeatureDataset != null)
                    {
                        if (results.ContainsKey(fc.FeatureDataset.Name))
                            results[fc.FeatureDataset.Name].Add(fc.AliasName);
                        else
                            results[fc.FeatureDataset.Name] = new List<string> {fc.AliasName};
                    }
                    else
                        Console.WriteLine("Skipping {0}...NOT within a Feature Dataset", fc.AliasName);
                    
                }
            }


            foreach (var kvp in results)
                Console.WriteLine("FEATURE DATASET: {0}\n...{1}\n", kvp.Key, String.Join("\n...", kvp.Value));


            Console.WriteLine();
            Console.Write("Press enter to exit...");
            Console.ReadLine();


            //ESRI License Initializer generated code.
            //Do not make any call to ArcObjects after ShutDownApplication()
            m_aoInit.ShutdownApplication();
        }
    }
}
StacyMcNeil
New Contributor II

Thank you Freddie.  This is very helpful.  Could you let me know what results.ContainsKey is doing and what the equivalent is in VB.NET.  I am new to ArcObject and so far have not been using c#. 

0 Kudos
FreddieGibson
Occasional Contributor III

That portion of the code is about using Dictionaries. You can read up on this concept on the following page:

C# Dictionary

http://www.dotnetperls.com/dictionary

This is a data structure in .NET that is not related to ArcObjects. Think of it like an actual dictionary. In a dictionary a word (i.e. key) will be defined once and the definition (i.e. value) will consist of multiple words, which can be repeated. I used the name of the feature dataset as the key in the dictionary and used the names of the feature classes as the values so that I easily organize which feature classes were in which feature dataset and print out a "prettier" list of the results.  If you want you could simplify this logic as follows:

ILayer layer;


//    while ( (layer = enumLayer.Next()) != null)
//    {
//        var fc = (layer as IFeatureLayer).FeatureClass;


//        if (fc.FeatureDataset != null)
//        {
//            if (results.ContainsKey(fc.FeatureDataset.Name))
//                results[fc.FeatureDataset.Name].Add(fc.AliasName);
//            else
//                results[fc.FeatureDataset.Name] = new List<string> {fc.AliasName};
//        }
//        else
//            Console.WriteLine("Skipping {0}...NOT within a Feature Dataset", fc.AliasName);


//    }
//}


//foreach (var kvp in results)
//    Console.WriteLine("FEATURE DATASET: {0}\n...{1}\n", kvp.Key, String.Join("\n...", kvp.Value));


while ((layer = enumLayer.Next()) != null)
{
    var fc = (layer as IFeatureLayer).FeatureClass;


    if (fc.FeatureDataset != null)
        Console.WriteLine("FEATURE CLASS: {0,-20} | FEATURE DATASET: {1}", fc.AliasName, fc.FeatureDataset.Name);
}

Below are screenshots of the results of these two options.

** Option A : using dictionary **

2015-09-22_1706.png

** Option B **

2015-09-22_1703.png