Hi I'm using ArcGIS Pro 2.9
I've created a custom tool that clips layers but I can't seem to save it to my default gdb.
// This works
string projectDirectory = Project.Current.HomeFolderPath;
// This does not
string projectDirectory = Project.Current.DefaultGeodatabasePath;
The problem with this is that I have additional functions that only seem to work with the clipped layer if it is saved in a GDB folder, not if it's in the project directory at the same level as the GDB file.
Why can't I save my clipped layer inside of the default GDB, especially when if you run the clip function manually it defaults to the default GDB location of the current project?
My custom clip function
public static class ClipHelper
{
public static async Task<bool> ClipLayers(string inputLayerUrl, FeatureLayer clipLayer, string outputLayerUrl)
{
try
{
// Ensure the clipLayer is not null and has features
if (clipLayer == null)
{
MessageBox.Show("Clip layer is null.");
return false;
}
// Check if the clipLayer has no features
if (clipLayer.GetFeatureClass().GetCount() == 0)
{
MessageBox.Show("Clip layer has no features. Clipping cannot proceed.");
return false;
}
// Create the parameter array for the Clip tool
var parameters = Geoprocessing.MakeValueArray(
inputLayerUrl, // Input Features or Dataset
clipLayer, // Clip Features (FeatureLayer)
outputLayerUrl // Output Features or Dataset
);
// Run the Clip geoprocessing tool
IGPResult result = await Geoprocessing.ExecuteToolAsync("analysis.Clip", parameters);
if (result.IsFailed)
{
MessageBox.Show($"Clip operation failed: {result.ErrorMessages}");
return false;
}
else
{
// MessageBox.Show("Clip operation completed successfully.");
return true;
}
}
catch (Exception ex)
{
MessageBox.Show($"Error during clip operation: {ex.Message}");
return false;
}
}
}
Where I'm running it:
private async Task ExportLayers(string clipLayerName)
{
await QueuedTask.Run(async () =>
{
// Get the current project's directory
string projectDirectory = Project.Current.HomeFolderPath;
//string projectDirectory = Project.Current.DefaultGeodatabasePath;
// Find the clip layer by name
var clipLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>()
.FirstOrDefault(lyr => lyr.Name.Equals(clipLayerName));
if (clipLayer == null)
{
MessageBox.Show($"The '{clipLayerName}' layer was not found in the table of contents.");
return;
}
foreach (var selectedItem in selectedItems)
{
Debug.WriteLine("Selected Item: " + selectedItem.LayerName);
// Check if there are specific URLs for this layer
if (selectedItem.SubLayers != null && selectedItem.SubLayers.Count > 0)
{
foreach (var subLayer in selectedItem.SubLayers)
{
// Access sublayer properties
string subLayerName = subLayer.SubLayerName;
string specificUrl = subLayer.SpecificUrl;
Debug.WriteLine($"SubLayer Name: {subLayerName}, Specific URL: {specificUrl}");
// Append "clipped" to the sublayer name for the output
string outputName = subLayerName + "_clipped";
// Create an output URL with the same name in the project directory
//string outputUrl = System.IO.Path.Combine(projectDirectory, outputName);
string outputUrl = projectDirectory + '\\' + outputName;
Debug.WriteLine(outputUrl);
// Call the ClipLayers method with the reference to the clip layer
bool clipResult = await ClipHelper.ClipLayers(specificUrl, clipLayer, outputUrl);
if (clipResult)
{
AddLocalFileToMap(specificUrl);
// Import symbology from the original layer to the clipped sublayer
ImportSymbology(subLayerName, outputName);
// Remove the original sublayer from the map (optional)
RemoveLayerByName(subLayerName);
}
else
{
// Handle the case where clipping failed
MessageBox.Show($"Clipping sublayer {subLayerName} failed.");
}
}
}
else
{
// Use a default URL or handle the case where sublayers are not available
MessageBox.Show("No sublayers available for this layer.");
}
}
Debug.WriteLine("Selected item count: " + selectedItems.Count);
});
}
Hi,
Have you checked your project database for existence of output name
subLayerName + "_clipped"
?
You need to check your project database and delete old one featureclass if exists or generate unique name when forming output featureclass name.
I would recommend you to run ExecuteToolAsync with GPToolExecuteEventHandler parameter as in sample.
You will get possibility to get information about invalid geoprocessing parameters.
var result = await Geoprocessing.ExecuteToolAsync(tool_path, args, null, _cts.Token,
(event_name, o) => // implement delegate and handle events
{
switch (event_name)
{
case "OnValidate": // stop execute if any warnings
if ((o as IGPMessage[]).Any(it => it.Type == GPMessageType.Warning))
_cts.Cancel();
break;
case "OnProgressMessage":
string msg = string.Format("{0}: {1}", new object[] { event_name, (string)o });
System.Windows.MessageBox.Show(msg);
_cts.Cancel();
break;
case "OnProgressPos":
string msg2 = string.Format("{0}: {1} %", new object[] { event_name, (int)o });
System.Windows.MessageBox.Show(msg2);
_cts.Cancel();
break;
}
});