Bug in Modifying Feature?

2253
23
Jump to solution
09-23-2019 01:59 PM
SusanFarley
New Contributor III

I have two Node layers in my map with the second layer being a copy of the first. I am enabling users to merge similar nodes to help clean up data, but all alterations are done on the copy layer in case the user later decides those nodes shouldn't be merged. So in my code I have:

//MergeRow is the new row and SelectedNodes is the list of rows to be deleted

public async Task<bool> MergeNodes(DataRow MergedRow, List<DataRow> SelectedNodes) {

      var modifyFeature = new EditOperation();

      modifyFeature.Name = "Merged Nodes";

      //Other stuff

      modifyFeature.Delete(MergeNodeLayer, Int64.Parse(SelectedNodes[0][oidNum].ToString()));

      modifyFeature.Execute();

     return true;

}

Even though I pass in the MergeNodeLayer, it deletes the node from both the control layer and the new layer. Is this a bug with delete or am I doing something wrong? The nodes on both layers have the same oids since it is a direct copy so it is deleting the correct one from each layer, but it should only be deleting the one for the layer I passed in.

Thank you,

Susan

Tags (3)
0 Kudos
23 Replies
by Anonymous User
Not applicable

Hi Susan,

To get the underlying featureclass path from a feature layer you'll have to concatenate the datastore path and the featureclass name. You can then feed this into the "mva" then into the geoprocessing tool. Note that if the featureclass was in a featuredataset in the datastore you would include that in the path too (determined from featureclass.GetFeatureDataset()).

Here's an example

      QueuedTask.Run(async () =>
      {
        //find hydrant layer
        var hydLayer = MapView.Active.Map.FindLayers("Hydrant").FirstOrDefault() as FeatureLayer;

        //get the underlying featureclass path for the layer
        var hydClass = hydLayer.GetFeatureClass();

        //get the datastore for the featureclass
        var hydStore = hydClass.GetDatastore();

        //concat hydrant path (datastore and featureclass name)
        var hydPath = hydStore.GetPath().AbsolutePath + @"/" + hydClass.GetName();

        //make the value array and pass to the GP tool
        var mva = Geoprocessing.MakeValueArray(@hydPath, $@"{hydPath}2");
        await Geoprocessing.ExecuteToolAsync("Copy_management", mva);
      });
0 Kudos
SusanFarley
New Contributor III

I must be doing something wrong. Here is my code:

public async Task<string[]> CopyLayer()

{

   var lyr = _arcFac.MainMapView.Map.GetLayersAsFlattenedList();

   string[] newLayers = new string[lyr.Count]();

   await QueuedTask.Run(() =>

   {

         foreach (BasicFeatureLayer fmLayer in lyr)

         {

               var hydLayer = MapView.Active.Map.FindLayers(fmLayer.Name).FirstOrDefault() as FeatureLayer; //I also tried this with = fmLayer as FeatureLayer and got the same result

        var hydClass = hydLayer.GetFeatureClass();

        var hydStore = hydClass.GetDatastore();

        var hydPath = hydStore.GetPath().AbsolutePath + @"/" + hydClass.GetName();

        var mva = Geoprocessing.MakeValueArray(@hydPath, $@"{hydPath}2");
        var res = Geoprocessing.ExecuteToolAsync("Copy_management", mva);

            }
      });

}

Though this does create lock files, it does not create new layers for me. I was originally running it with files on a network share drive, I moved those files locally and tried again. I get the same result. "res" does not contain an error and just says awaiting thread to complete. Any ideas? I cannot send you my direct code or my shape files. Sorry.

Thank you,

Susan

0 Kudos
by Anonymous User
Not applicable

Hi Susan,

Finding the layers twice is a bit of overkill so assuming you just want to work with featurelayers, you can change the first list to:

var lyr = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>();

Your foreach loop then looks like:

foreach (var fmLayer in lyr)

then you can get the featureclass from your fmLayer instead of hydlayer etc.

 

Next, set a break point and run the add-in through the debugger, stepping through the code to see if the values make sense. Ideally through each loop the mva variable should look correct:

0 Kudos
SusanFarley
New Contributor III

My mva is:

"C:/Temp/all_nodes_shp"

"C:/Temp/all_nodes_shp2"

and my res2 is:

AyncState = null

CancellationPending = false

CreationOptions = None

Exception = null

ID = some number

Result = null

Status = WaitingToRun

Does it matter that I am using shape files? Should the hydPath include the .shp extention?

Thank you,

Susan

0 Kudos
SusanFarley
New Contributor III

That was it. It needed the extension.

Thank you,

Susan

0 Kudos
SusanFarley
New Contributor III

Do you know how to programmatically get the file extension since I won't know if the user is using shapefiles, layers, or a gdb file?

Thank you,

Susan

0 Kudos
by Anonymous User
Not applicable

Hi Susan,

Yes, again its a bit convoluted.

        //get the datastore for the featureclass
        var hydStore = hydClass.GetDatastore();

        if (hydStore is FileSystemDatastore)
        {
          var cp = hydStore.GetConnector() as FileSystemConnectionPath;
          var t = cp.Type; //shapefile or raster?
        }

From the featureclass you get the datastore which is a type of filesystem (shapefiles or raster), local or enterprise. For the filesystemdatastore you can further identify a shapefile or raster source. You cant directly get the shapefile extension.

Ive asked the geodatabase team to make this whole thing easier...

0 Kudos
SusanFarley
New Contributor III

Thank you! This works great for shape files and raster files, but I was just testing for files in a geodatabase and it does not work. We are so close.

foreach (BasicFeatureLayer fmLayer in lyr)

         {

               var hydLayer = fmLayer as FeatureLayer

        var hydClass = hydLayer.GetFeatureClass();

        var hydStore = hydClass.GetDatastore();

        string fileExtention = "";

        

        if (hydStore is FileSystemDatastore)

                {

                     var cp = hydStore.GetConnector() as FileSystemConnectionPath;

                     if (cp.Type == FileSystemDataStpreType.Shapefile)

                                          fileExtention = ".shp";

                }

               //fileExtention is an empty string in the case of a geodb.

        var hydPath = hydStore.GetPath().AbsolutePath + @"/" +

                                 hydClass.GetName() + fileExtention;

        var mva = Geoprocessing.MakeValueArray(@hydPath, $@"{hydPath}2") + fileExtention;
        var res = Geoprocessing.ExecuteToolAsync("Copy_management", mva);

            }

0 Kudos
by Anonymous User
Not applicable

Hi Susan,

I'd probably just do the extension as part of the mva string so it becomes:

        //concat hydrant path (datastore and featureclass name)
        var hydPath = hydStore.GetPath().AbsolutePath + @"/" + hydClass.GetName();

        //make the value array and pass to the GP tool
        var mva = Geoprocessing.MakeValueArray(@hydPath + fileExtention, $@"{hydPath}2" + fileExtention);
        await Geoprocessing.ExecuteToolAsync("Copy_management", mva);

This should work for all types.

0 Kudos
SusanFarley
New Contributor III

It works for everything except when the files are part of a gdb file. I have a SmallTest.gdb with two layers in it. hydstor is a Geodatabase. When I try the code above to create copies of them, it doesn't. There are no errors. The res is:

AyncState = null

CancellationPending = false

CreationOptions = None

Exception = null

ID = some number

Result = null

Status = WaitingToRun

So it is like before when I didn't have the proper file extension. 

Thank you,

Susan

0 Kudos