ArcObjects features not in featuredataset

2372
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
Regular Contributor II

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
Regular Contributor II

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