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
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();
}
}
}
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#.
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 **

** Option B **
