|
POST
|
I use the following steps to solve these types of CIM related configuration problems: First I use the Pro UI to create a Grid in my Layout's MapFrame to fulfill my requirements. I then create a test add-in with one button and insert the following code snippet into the button's code-behind: protected override void OnClick()
{
LayoutView activeLayoutView = LayoutView.Active;
if (activeLayoutView == null)
{
MessageBox.Show("No active Layout");
return;
}
var mapframe = activeLayoutView.ActiveMapFrame;
if (mapframe == null)
{
MessageBox.Show("No active MapFrame");
return;
}
QueuedTask.Run(() =>
{
var mapFrameDefinition = mapframe.GetDefinition();
CIMMapFrame cimMapFrame = mapFrameDefinition as CIMMapFrame;
System.IO.File.WriteAllText(@"c:\temp\mapgrid.xml", cimMapFrame.ToXml());
});
} When running the test add-in I select my layout and make my MapFrame the active map frame. After I used my test button I can then open the output file: c:\temp\mapgrid.xml in Visual Studio. Using the output 'CIMMapFrame' structure I use the XML to find and examine the GridLines that were defined by ArcGIS Pro:
... View more
08-18-2021
10:26 AM
|
0
|
0
|
1662
|
|
POST
|
To elaborate a bit on Ken's suggestion above and what Charlie put into practice, you want to avoid a pattern where QueuedTask.Run () is called from within the context of a QueuedTask.Run action. This can lead to dead locks. When you said: "When put into a function it doesn't work - not error just exits the function". This is expected behavior for any asynchronous function if you call the method without specifying an 'await'. In your question above you didn't show how you called the method which didn't work. Put a breakpoint into your 'async void CreateMaps' method and see if you hit that breakpoint (you should hit it actually). Also you should always add some error handling using a try {} catch {}.
... View more
08-18-2021
07:53 AM
|
0
|
0
|
1559
|
|
POST
|
This sample code worked for me: protected override async void OnClick()
{
try
{
var environment = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);
var defaultGDB = Project.Current.DefaultGeodatabasePath;
var srcLayer = "TestPoints";
var srcGdb = @"C:\Data\FeatureTest\FeatureTest.gdb";
var outputFeatureClass = @"TestTestPoints";
var fields = new string[] {
@"TheDate ""TheDate"" true true false 8 Date 0 0,First,#,TestPoints,TheDate,-1,-1",
@"CodePoint ""CodePoint"" true true false 4 Long 0 0,First,#,TestPoints,CodePoint,-1,-1",
@"TheString ""TheString"" true true false 255 Text 0 0,First,#,TestPoints,TheString,0,255",
@"TheInteger ""TheInteger"" true true false 4 Long 0 0,First,#,TestPoints,TheInteger,-1,-1",
@"TheDouble ""TheDouble"" true true false 8 Double 0 0,First,#,TestPoints,TheDouble,-1,-1",
@"NewString ""NewString"" true true false 255 Text 0 0,First,#,TestPoints,TheString,0,255'" };
var fieldMap = string.Join (";", fields);
var toolParameters = Geoprocessing.MakeValueArray(srcLayer, srcGdb, outputFeatureClass, null, fieldMap, null);
GPExecuteToolFlags executeFlags = GPExecuteToolFlags.AddOutputsToMap | GPExecuteToolFlags.GPThread | GPExecuteToolFlags.AddToHistory | GPExecuteToolFlags.RefreshProjectItems;
IGPResult gpResult = await Geoprocessing.ExecuteToolAsync("FeatureClassToFeatureClass", toolParameters, environment, null, null, executeFlags);
Geoprocessing.ShowMessageBox(gpResult.Messages, "GP Messages", gpResult.IsFailed ? GPMessageBoxStyle.Error : GPMessageBoxStyle.Default);
}
catch (Exception ex)
{
MessageBox.Show($@"Error: {ex}");
}
}
... View more
08-17-2021
01:57 PM
|
0
|
6
|
4155
|
|
POST
|
Are you using the Pro SDK to define the 'definition query'? You should see on the bottom of the dialog the current active 'definition query', as shown on the screen shot below. Can you share what RDMS you are using and also a sample of you 'definition query' in sql format? If you use the Pro SDK can you share a code snippet for your 'definition query'?
... View more
08-16-2021
09:49 AM
|
2
|
3
|
7582
|
|
POST
|
I will check with the dev team next week, however, i found that the order of the precision and scale parameters are switched. Depending on those values the field type was changed. The following snippet worked for me when using a shapfile (it's a simple button in an add-in module and all paths and values are hard coded): internal class AddDoubleToShape : Button
{
protected override async void OnClick()
{
var shpPath = $@"C:\Data\FeatureTest\shapefile\base_state.shp";
var fldName = "DTest";
var alias = "";
var fldType = "DOUBLE";
var precision = 11;
var scale = 3;
var result = await ExecuteAddFieldTool(shpPath, fldName, alias, fldType, scale, precision, null, true);
}
/// <summary>
/// Adds a field to a table using GP
/// </summary>
/// <param name="shpPath"></param>
/// <param name="fieldName"></param>
/// <param name="fieldAlias"></param>
/// <param name="fieldType"></param>
/// <param name="precision"></param>
/// <param name="scale"></param>
/// <param name="fieldLength"></param>
/// <param name="isNullable"></param>
/// <returns>true: if field was added</returns>
private async Task<bool> ExecuteAddFieldTool(string shpPath, string fieldName,
string fieldAlias,
string fieldType, int precision, int scale,
int? fieldLength = null, bool isNullable = true)
{
try
{
return await QueuedTask.Run(() =>
{
// from arcpy command (from geoprocessing dockpane / share):
// arcpy.management.AddField(r"C:\Data\FeatureTest\shapefile\base_state.shp",
// "TestMyD", // name
// "DOUBLE", // type
// 2, // scale
// 10, // precision (reversed order ? with scale ?)
// None, // length
// '', // name
// "NULLABLE",
// "NON_REQUIRED",
// '')
var parameters = Geoprocessing.MakeValueArray(shpPath, fieldName,
fieldType.ToUpper(), scale, precision,
fieldLength, fieldAlias, isNullable ? "NULLABLE" : "NON_NULLABLE");
var cts = new CancellationTokenSource();
var result = Geoprocessing.ExecuteToolAsync("management.AddField", parameters, null, cts.Token,
(eventName, o) =>
{
System.Diagnostics.Debug.WriteLine($@"GP event: {eventName}");
});
return !result.Result.IsFailed && !result.Result.IsCanceled;
});
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
}
}
... View more
08-13-2021
05:08 PM
|
0
|
0
|
1519
|
|
POST
|
Use FrameworkApplication.SetCurrentToolAsync to set the current tool using the tool's daml id. // pass the tool's daml id as parameter
FrameworkApplication.SetCurrentToolAsync("esri_mapping_exploreTool");
... View more
08-11-2021
04:40 PM
|
1
|
0
|
1002
|
|
POST
|
If you are using an Enterprise Geodatabase you should take a look at this built-in feature: What is archiving?—ArcGIS Pro | Documentation
... View more
08-11-2021
10:23 AM
|
0
|
0
|
3241
|
|
POST
|
You can change the SketchOutputMode in your tool to SketchOutputMode.Map. This should get you the sketch geometry in the same spatial reference as your map. public MapToolIdentifyWithDockpane()
{
IsSketchTool = true;
SketchType = SketchGeometryType.Rectangle;
SketchOutputMode = SketchOutputMode.Map;
} If you need to project your geometry using a different coordinate system you can use GeometryEngine: var geomProjected = GeometryEngine.Instance.Project(geometry, SpatialReferences.WebMercator);
... View more
08-11-2021
10:13 AM
|
1
|
2
|
5508
|
|
POST
|
No, you have to leave the editOperation.Modify line in the code, even so your 'sourcePolygon' will be overwritten in the callback. The editOperation.Modify triggers the callback, the callback in turn then writes the 'untouched' sourcePolygon geometry through the geodatabase API. We know at this point that there is some problem with the sourcePolygon geometry, we don't know what the exact problem is yet. The reason why you get an empty geometry is because EditOperation will 'simplify' every geometry before saving it in the geodatabase. Apparently this 'simplification' is the not working correctly and results in an empty geometry. We are trying to find what the issue with the geometry is and also a method to fix it. We tried some of the GP tools to fix the geometry but those had the same problem. Anyways i will keep you updated on our progress, but for now that's the only workaround we have. Also remember that your geometry still has an issue even once you write it directly into the geodatabase, so editing in Pro will not work for this geometry.
... View more
08-11-2021
09:36 AM
|
0
|
5
|
1937
|
|
POST
|
Strange, both feature classes you sent me have 'No Z values'. That would mean that z-values got added to the geometry. Can you double check your feature classes ? I used v 2.8.2.
... View more
08-10-2021
01:27 PM
|
0
|
1
|
2999
|
|
POST
|
Hi Karen, We are still trying to figure out what exactly is causing this issue. It appears to be data related. In the meantime I received a workaround that will fix this issue for the time being. The workaround writes over the 'null' geometry in an EditOperation call back, it is using the Geodatabase API to do so. The Geodatabase API doesn't seem to have any problems with the data. I modified the code you sent me with the EditOperation call back workaround below. protected override async void OnClick()
{
var sourceLayerName = "Source";
var modifyLayerName = "Modify";
var SourceFieldName = "OBJECTID";
var ModifyFieldName = "OBJECTID";
var selectionSourceQuery = $@"{SourceFieldName} = 1";
var selectionModifyQuery = $@"{ModifyFieldName} = 117";
var sourceLayer = MapView.Active.Map.GetLayersAsFlattenedList().Where((l) => l.Name == sourceLayerName).FirstOrDefault() as FeatureLayer;
if (sourceLayer == null)
{
MessageBox.Show($@"Unable to find {sourceLayerName} in the active map");
return;
}
var modifyLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault(f => f.Name == modifyLayerName);
if (modifyLayer == null)
{
MessageBox.Show($@"Unable to find {modifyLayerName} in the active map");
return;
}
await QueuedTask.Run(() =>
{
// search the source for the matching parcel record
// copy only one polygon
Geometry sourcePolygon = null;
using (var cursor = sourceLayer.Search(new QueryFilter() { WhereClause = selectionSourceQuery }))
{
if (cursor.MoveNext())
{
using (var myFeature = cursor.Current as Feature)
{
sourcePolygon = myFeature.GetShape().Clone();
}
}
}
if (sourcePolygon == null)
{
MessageBox.Show($@"The add-in was not able to find a parcel where '{selectionSourceQuery}' is true.");
return;
}
using (Table table = modifyLayer.GetTable())
{
EditOperation editOperation = new EditOperation
{
Name = "Modify a geometry callback"
};
editOperation.Callback(context =>
{
QueryFilter filter = new QueryFilter { WhereClause = selectionModifyQuery };
using (RowCursor rowCursor = table.Search(filter, false))
{
while (rowCursor.MoveNext())
{
using (Feature feature = (Feature)rowCursor.Current)
{
// In order to update the Map and/or the attribute table.
// Has to be called before any changes are made to the row.
context.Invalidate(feature);
feature.SetShape(sourcePolygon);
//After all the changes are done, persist it.
feature.Store();
// Has to be called after the store too.
context.Invalidate(feature);
}
}
}
}, table);
// create the polygon feature
editOperation.Modify(modifyLayer, 117, sourcePolygon);
if (!editOperation.Execute())
{
MessageBox.Show($@"Unable to create a new '{sourceLayer}' record: {editOperation.ErrorMessage}");
}
}
});
} I will give you an update on our findings.
... View more
08-10-2021
12:07 PM
|
0
|
6
|
3013
|
|
POST
|
I modified the MapToolIdentifyWithDockpane sample and added the selection (by rectangle) button on the same identify dockpane. I attached the sample project, maybe this will be of help.
... View more
08-10-2021
11:45 AM
|
0
|
2
|
5525
|
|
POST
|
Thanks Karen, Thangs for the sample data. I am able to replicate what you are seeing with your data, however, in my tests the copied geometry is 'nulled' regardless on my language / region settings. I will let you know what i find.
... View more
08-10-2021
07:37 AM
|
0
|
1
|
3033
|
|
POST
|
Hi Karen, I was not able to duplicate the issue you are seeing. I attached my test add-in (2.8.2) and my test project. You click a button on the test add-in it first creates a new feature and then updates the same feature on subsequent clicks. Also, is it possible that the geometry you are copying into the modified feature is disposed by the time you are calling editOperation.Execute()? Note that in my sample I use .Clone() to prevent this from happening. // search the source for the matching parcel record
// copy only one polygon
Geometry parcelPolygon = null;
using (var cursor = sourceLayer.Search(new QueryFilter() { WhereClause = selectionSourceQuery }))
{
if (cursor.MoveNext())
{
using (var parcelFeature = cursor.Current as Feature)
{
// note: cloning the gemetry makes sure that the
// geometry persists outside the context of the cursor
parcelPolygon = parcelFeature.GetShape().Clone();
}
}
}
... View more
08-06-2021
11:50 AM
|
0
|
1
|
4113
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 10-29-2025 10:48 AM | |
| 1 | 05-24-2021 09:04 AM | |
| 1 | 12-03-2020 08:44 AM | |
| 1 | 10-07-2025 07:27 AM | |
| 2 | 12-29-2025 10:03 AM |
| Online Status |
Offline
|
| Date Last Visited |
05-21-2026
01:59 PM
|