I am creating a featureclass using the following code.
var result = await CreateLayer(System.IO.Path.GetDirectoryName(output), System.IO.Path.GetFileName(output), "POINT", SR.Wkid);
if (result == null) return;
var featurelayer = ?
public static async Task<IGPResult> CreateLayer(string path, string featureclassName, string featureclassType, int SR_wkid)
{
List<object> arguments = new List<object>
{
// store the results in the default geodatabase
//CoreModule.CurrentProject.DefaultGeodatabasePath,
path,
// name of the feature class
featureclassName,
// type of geometry
featureclassType,
// no template
"",
// no z values
"DISABLED",
// no m values
"DISABLED"
};
await QueuedTask.Run(() =>
{
// spatial reference
arguments.Add(SpatialReferenceBuilder.CreateSpatialReference(SR_wkid));
});
IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", Geoprocessing.MakeValueArray(arguments.ToArray()));
return result;
}
CreateLayer automatically adds the featureclass to the map. How do I get a reference to this featurelayer? Is this the only way or can I get it directly from the IGResult?
var fcLayer = MapView.Active.Map.GetLayersAsFlattenedList().Where((l) => l.Name == fcName).FirstOrDefault() as BasicFeatureLayer;
Solved! Go to Solution.
You can disable the automatic adding of the feature class to the current map by changing the GPExecuteToolFlags.AddOutputsToMap option (which is the default) to GPExecuteToolFlags.None, as shown in the snippet below.
IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management",
Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, GPExecuteToolFlags.None);
After this is done, you can add the layer yourself, as shown in my Button 'OnClick' sample below:
protected override async void OnClick()
{
await CreateFeatureClass("TTT", EnumFeatureClassType.POINT);
}
public enum EnumFeatureClassType
{
POINT,
MULTIPOINT,
POLYLINE,
POLYGON
}
/// <summary>
/// Create a feature class in the default geodatabase of the project.
/// </summary>
/// <param name="featureclassName">Name of the feature class to be created.</param>
/// <param name="featureclassType">Type of feature class to be created. Options are:
/// <list type="bullet">
/// <item>POINT</item>
/// <item>MULTIPOINT</item>
/// <item>POLYLINE</item>
/// <item>POLYGON</item></list></param>
/// <returns></returns>
public static async Task CreateFeatureClass(string featureclassName,
EnumFeatureClassType featureclassType)
{
List<object> arguments = new List<object>
{
// store the results in the default geodatabase
CoreModule.CurrentProject.DefaultGeodatabasePath,
// name of the feature class
featureclassName,
// type of geometry
featureclassType.ToString(),
// no template
"",
// no z values
"DISABLED",
// no m values
"DISABLED"
};
await QueuedTask.Run(() =>
{
// spatial reference
arguments.Add(SpatialReferenceBuilder.CreateSpatialReference(3857));
});
IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management",
Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, GPExecuteToolFlags.None);
var uri = new Uri(result.ReturnValue);
var lyr = await QueuedTask.Run<FeatureLayer>(() =>
{
var newLayer = LayerFactory.Instance.CreateFeatureLayer(uri,
MapView.Active.Map, LayerPosition.AddToTop, $@"Lyr-{featureclassName}") as FeatureLayer;
return newLayer;
});
MessageBox.Show($@"Newly added: {lyr.Name}");
}
You can also use the result.ReturnValue GDB path to find the automatically added layer by comparing all feature layer datasources for the current map.
You can disable the automatic adding of the feature class to the current map by changing the GPExecuteToolFlags.AddOutputsToMap option (which is the default) to GPExecuteToolFlags.None, as shown in the snippet below.
IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management",
Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, GPExecuteToolFlags.None);
After this is done, you can add the layer yourself, as shown in my Button 'OnClick' sample below:
protected override async void OnClick()
{
await CreateFeatureClass("TTT", EnumFeatureClassType.POINT);
}
public enum EnumFeatureClassType
{
POINT,
MULTIPOINT,
POLYLINE,
POLYGON
}
/// <summary>
/// Create a feature class in the default geodatabase of the project.
/// </summary>
/// <param name="featureclassName">Name of the feature class to be created.</param>
/// <param name="featureclassType">Type of feature class to be created. Options are:
/// <list type="bullet">
/// <item>POINT</item>
/// <item>MULTIPOINT</item>
/// <item>POLYLINE</item>
/// <item>POLYGON</item></list></param>
/// <returns></returns>
public static async Task CreateFeatureClass(string featureclassName,
EnumFeatureClassType featureclassType)
{
List<object> arguments = new List<object>
{
// store the results in the default geodatabase
CoreModule.CurrentProject.DefaultGeodatabasePath,
// name of the feature class
featureclassName,
// type of geometry
featureclassType.ToString(),
// no template
"",
// no z values
"DISABLED",
// no m values
"DISABLED"
};
await QueuedTask.Run(() =>
{
// spatial reference
arguments.Add(SpatialReferenceBuilder.CreateSpatialReference(3857));
});
IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management",
Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, GPExecuteToolFlags.None);
var uri = new Uri(result.ReturnValue);
var lyr = await QueuedTask.Run<FeatureLayer>(() =>
{
var newLayer = LayerFactory.Instance.CreateFeatureLayer(uri,
MapView.Active.Map, LayerPosition.AddToTop, $@"Lyr-{featureclassName}") as FeatureLayer;
return newLayer;
});
MessageBox.Show($@"Newly added: {lyr.Name}");
}
You can also use the result.ReturnValue GDB path to find the automatically added layer by comparing all feature layer datasources for the current map.
Thanks, the GPExecuteToolFlags.None option is good to know. I had figured out to use the LayerFactory, but didn't know how to get around the automatic add.
Hi Wolf,
I am new to this forum and am not sure if this qualifies as a new question. I have a scenario similar to your answer code above. However, the geoprocessing tool I am running is one that generates a layer rather than writing a feature class to disk. This tool could be "MakeFeatureLayer_management" or "AddJoin_management", for example. I DO NOT want this geoprocessing tool output to be added as a layer to the map. My issue is this: those geoprocessing tools run properly and output the layer name as a string value which I can retrieve. However, I am unsure how to pass a reference to the freshly-created layer to the next tool (e.g. "CopyFeatures_management") in my code. If I allow tool output to be added to my map, I can find that layer based on the tool output name, but if I do not allow the output to be added to the map, then my next tools (e.g. "CopyFeatures_management") do not recognize the output name as a valid input. It is as if the "MakeFeatureLayer_management" tool's layer output simply vanishes and is unreferenceable by subsequent tools, UNLESS the layer is added by the tool to the map.
See your code fragment below - I've replaced "CreateFeatureclass_management" with "MakeFeatureLayer_management". GPExecuteToolFlags.None will ensure that no layer gets output to the map. So, how can I pass on the new feature layer output by this tool to my next tool as an input (e.g. CopyFeatures_management)??
IGPResult result = await Geoprocessing.ExecuteToolAsync("MakeFeatureLayer_management",
Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, GPExecuteToolFlags.None);
Hopefully I am just missing a simple solution to this scenario. Python allows the user to use the output of a layer-producing tool (a name string) as an input to the next tool even if the tool outputs are not loaded into the map. I don't see how to do this using the .NET SDK. help!
I have the same scenario , The AddJoin GP tool, I don't want to add the output layer to the map.Has the problem been solved?
Did you see the answer accepted as the solution?
You can disable the automatic adding of the feature class to the current map by changing the GPExecuteToolFlags.AddOutputsToMap option (which is the default) to GPExecuteToolFlags.None, as shown in the snippet below.
Our team, like you, initially had a method called CreateFeatureLayer but your method like ours was actually calling a GP Tool (CreateFeatureclass_management) that is creating a FeatureClass. And it just so happens that the default behavior of the Geoprocessing.ExecuteToolAsync() method is to also add the FeatureClass to the active map as a FeatureLayer. But there are times you don't want to do this and the accepted solution is the way to go. I would recommend you change the name of your method to CreateFeatureClass. That's what we did and we also added a boolean option to Add to Map that defaults to false so you have the option to do so or not.
Additionally, there are times you do need to find if a layer has been added or not and obtain a reference to the same. I prefer the code snippet below unless there is a better one.
FeatureLayer l_returnLayer = MapView.Active.Map.FindLayers(a_layerName).FirstOrDefault() as FeatureLayer;
Pro 2.8 will contain some DDL functionality, in case you want to create a table without adding it to the map.
--Rich