Getting a featurelayer from a Geoprocessing result

158
4
Jump to solution
3 weeks ago
KenBuja
MVP Honored Contributor

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;

 

0 Kudos
1 Solution

Accepted Solutions
Wolf
by Esri Regular Contributor
Esri Regular Contributor

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.

View solution in original post

0 Kudos
4 Replies
Wolf
by Esri Regular Contributor
Esri Regular Contributor

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.

View solution in original post

0 Kudos
KenBuja
MVP Honored Contributor

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.

0 Kudos
DHuantes
New Contributor III

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;

 

0 Kudos
RichRuh
Esri Regular Contributor

Pro 2.8 will contain some DDL functionality, in case you want to create a table without adding it to the map.

--Rich

0 Kudos