I am trying load an jpg file as a raster layer, start georeferencing and then fit to display the raster.
This part of a larger ArcGIS Pro 3.5 project, where the image file name is found using user input from a wpf form. It is written in C#.
This is a rejig of an existing ArcMap 10.8 ArcObjects project writen in VB.Net
The idea is to place the image roughly in the right place ready for the user to georeferencing workflow.
Previously I have acquired the image and added it to the table of contents. This all works fine.
I have separated out the execution of esri commands into its own function. There is a bool parameter the writes a Messagebox if true saying if the command is executed or not.
The behavior I find:
if all three steps (attempt to close georeference session, start georeferencing, execute "fit to display") report their status then the image is displayed in the center of the current extent i.e "fit to display" is executed. After manually stopping georeferencing and removing the raster image, I can repeat the commands and the image is again displayed in the center of the current extent.
My code does the following: related commands:
The step esri_datasourcesraster_georefCloseSessionButton cannot be executed. I believe this is because there is a user dialog required to save/stop a Georeferencing session.
I use a separate function to execute the esri commands. This has an option to report if the command was executed or not via a Messagebox.
This all works repeatedly if and only I switch on reporting i.e. the user responds to a total of 3 messages when i execute the georefCloseSessionButton , georefStartButton and georefFitToDisplayButton.
However if I switch off reporting for even one step it will not "fit to display" for many combinations. It will work for the first load when the georeferencing button reports on its status. It only works once if I do not attempt to stop the geoprocessing but report the other 2 steps.
Similar behavior occurs if I do not include the initial esri_datasourcesraster_georefCloseSessionButton step.
Also it will "fit to display" just the first time if I do not do any reporting but I add a delay after the start georeferencing button is activated.
I have tested this in all sorts of ways .
Questions:
Thanks
Stefan
The following code is placed in a utility class. The functions are called from within button bound to an ICoomand i.e.
public ICommand cmdLoad
{
get
{
return new RelayCommand(async () =>
{
// Get image ame from
await clsUtils.AddImageToMap(imagepath);
await clsUtils.MoveImageToDisplay(ImageName);
}, true);
}
}
The utility class functions:
public static class clsUtils ...
public static async Task MoveImageToDisplay(string layerName)
{
string procName = nameof(MoveImageToDisplay);
// MoveImageToDisplay
try
{
// to use Geroeferenceing need a raster layer to be selected
MapView mapView = MapView.Active;
var myMap = mapView?.Map;
RasterLayer targetlayer = myMap.GetLayersAsFlattenedList().OfType<RasterLayer>().FirstOrDefault(l => l.Name.Equals(layerName, System.StringComparison.OrdinalIgnoreCase));
List<RasterLayer> layersToSelect = new List<RasterLayer>();
layersToSelect.Add(targetlayer);
MapView.Active.SelectLayers(layersToSelect);
bool report = true;
// always attempt to close down any georeferencing
// Does not work. Probably because it requires user input. The dialog box does not appear.
// Does no seem to matter if on or not
clsUtils.ExecuteESRICommand("esri_datasourcesraster_georefCloseSessionButton",report);
// Activate Georeferencing Tab
// I found that i didn't need to activate the Imagry Tab first as is needed when working manually.
string activeTabId = FrameworkApplication.ActiveTab;
if (activeTabId != "esri_mapping_georeference_GeoreferenceTab")
{
//FrameworkApplication.ActivateTab("esri_datasourcesraster_imageryCoreTab");
FrameworkApplication.ActivateTab("esri_datasourcesraster_GeoreferenceTab");
}
// Start georeferencing
clsUtils.ExecuteESRICommand("esri_datasourcesraster_georefStartButton",report);
// Add a delay
//await System.Threading.Tasks.Task.Delay(1000);
// execute the "FitToDisplay" georeferenciong command
clsUtils.ExecuteESRICommand("esri_datasourcesraster_georefFitToDisplayButton",report);
//Switch on seleceted layers if not aleady on
foreach (RasterLayer layer in layersToSelect)
{
if (!layer.IsVisible)
{
await QueuedTask.Run(() =>
{
layer.SetVisibility(true); // on MCT
});
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error ( " + procName + " ) " + ex.Message + Environment.NewLine + Environment.NewLine + ex.StackTrace);
}
}
public static void ExecuteESRICommand(string commandId, bool report = false )
{
//var commandId = "esri_datasourcesraster_georefFitToDisplayButton";
// get the ICommand interface from the ArcGIS Pro Button
// using command's plug-in wrapper
var iCommand = FrameworkApplication.GetPlugInWrapper(commandId) as ICommand;
if (iCommand != null)
{
// Let ArcGIS Pro do the work for us
if (iCommand.CanExecute(null))
{
iCommand.Execute(null);
if(report) MessageBox.Show(commandId + " executed");
}
else
{
if(report) MessageBox.Show("Cannot exexcute " + commandId);
}
}
else
{
if(report) MessageBox.Show( commandId + " is null");
}
}
I tried to use an asynchronous version of the ExecuteESRICommand, but this didn't work.
If all three commands are executed "Fit to Display" is done but then Pro crashes.
public static async Task ExecuteESRICommandAsync(string commandId, bool report = false)
{
// get the ICommand interface from the ArcGIS Pro Button
// using command's plug-in wrapper
var iCommand = FrameworkApplication.GetPlugInWrapper(commandId) as ICommand;
if (iCommand != null)
{
// Let ArcGIS Pro do the work for us
if (iCommand.CanExecute(null))
{
await QueuedTask.Run(() =>
{
iCommand.Execute(null);
});
if (report) MessageBox.Show(commandId + " executed");
}
else
{
if (report) MessageBox.Show("Cannot exexcute " + commandId);
}
}
else
{
if (report) MessageBox.Show(commandId + " is null");
}
}