Equivalent to Arcpy's updateConnectionProperties

1741
9
Jump to solution
09-15-2020 06:34 AM
TomGeo
by
Occasional Contributor III

I have a couple of map panes in ArcGIS Pro where the data source might differ from one occasion to te other. However, the name of the FeatureLayers are constant.

I am trying to adjust the underlaying data source based on user input. Meaning, the user has an OpenItemDialog listening on geodatabases. Plan is to use the retrieved path for the update.

However, I don't succeed. 

In the following code snippet the selectedMapAjour is of type Map

if (selectedMapAjour != null && !string.IsNullOrEmpty(PathGdbAjour))
{
    foreach (FeatureLayer layer in selectedMapAjour.Layers.OfType<FeatureLayer>())
    {
        GetSetDataConnection(layer, PathGdbAjour);
    }
}

private async void GetSetDataConnection(FeatureLayer layer, string newGDB)
{
    await QueuedTask.Run(() =>
    {
        CIMFeatureLayer def = layer.GetDefinition() as CIMFeatureLayer;
        var dcon = def.FeatureTable.DataConnection as CIMStandardDataConnection;
        dcon.WorkspaceConnectionString = System.IO.Path.Combine(newGDB, layer.Name);
        layer.SetDefinition(def);
    });
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The code runs through... only the exclamation mark in the TOC of the map do not disappear. Although, the path set via dcon.WorkspaceConnectionString is reflected in the properties of the FeatureLayers in the TOC.

Hence, I am not sure if my attempt to alter the data source worked and I am missing some refresh or update call, or if this does not work at all.

I basically need a C# equivalent of updateConnectionProperties.

Thereafter, I will have to adjust the symbology, so ApplySymbologyFromLayer would be next. 

Does anybody has an example for this stuff?

Best Thomas

- We are living in the 21st century.
GIS moved on and nobody needs a format consisting out of at least three files! No, nobody needs shapefiles, not even for the sake of an exchange format. Folks, use GeoPackage to exchange data with other GIS!
0 Kudos
1 Solution

Accepted Solutions
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Thomas Becker‌,

 I used the following code snippet to change the data source for my feature layers:

private async void ChangeDatasource(FeatureLayer featLayer, string newGDB)
{
		await QueuedTask.Run(() =>
		{
			// provide a replacement data connection object
			CIMDataConnection updatedDataConnection = new CIMStandardDataConnection()
			{
				WorkspaceConnectionString = $"DATABASE={newGDB}",
				WorkspaceFactory = WorkspaceFactory.FileGDB,
				DatasetType = esriDatasetType.esriDTFeatureClass,
				Dataset = featLayer.Name
			};
			// the updated Data connection should look like this:
			// CustomWorkspaceFactoryCLSID: null
			// Dataset: "TestMultiPoints"
			// DatasetType: esriDTFeatureClass
			// WorkspaceConnectionString: "DATABASE=C:\\Data\\FeatureTest\\FeatureTest.gdb"
			// WorkspaceFactory: FileGDB

			// overwrite the data connection
			featLayer.SetDataConnection(updatedDataConnection);
		});
}

In my tests (using 2.6) I didn't need to refresh the map view, the content of my replacement data was immediately displayed.  

View solution in original post

0 Kudos
9 Replies
RichRuh
Esri Regular Contributor

Thomas,

Have you tried calling Map.Redraw(True) after your code above?

--Rich

0 Kudos
TomGeo
by
Occasional Contributor III

Hi Rich,

I did not call Map.Redraw, but I have now...

Since Map.Redraw is called on the MapView object I had to switch from the Map object to MapView.

Hence, selectedMapAjour is now of type MapView.

The code look now as follows:

if (selectedMapAjour != null && !string.IsNullOrEmpty(PathGdbAjour))
{
    foreach (FeatureLayer layer in selectedMapAjour.Map.Layers.OfType<FeatureLayer>())
    {
        GetSetDataConnection(selectedMapAjour, layer, PathGdbAjour);
    }
}

private async void GetSetDataConnection(MapView mapview, FeatureLayer layer, string newGDB)
{
    await QueuedTask.Run(() =>
    {
        CIMFeatureLayer def = layer.GetDefinition() as CIMFeatureLayer;
        var dcon = def.FeatureTable.DataConnection as CIMStandardDataConnection;
        dcon.WorkspaceConnectionString = System.IO.Path.Combine(newGDB, layer.Name);
        dcon.Dataset = layer.Name;
        layer.SetDefinition(def);
        mapview.Redraw(true);
    });
}

Line 18 does not change the result.

When I adjust the data source for a layer manually, then I have to select the appropriate feature class within the geodatabase. Confirming the 'Change Data Source' dialogue makes the layer properties dialogue flash and thereafter the property for the database contains the path to the database. All other information of the layers data source properties are populated. The property 'Feature Class' does not only have the name of the feature class but also a button, holding information about the 'Object Class ID'.

When I run my code, the property for the database in the layer property dialogue is showing the entire path, down to the feature class

C:\Projects\Support\geo_507474_20200721_12_42.gdb\Bassin.

The property for Feature Class in the dialogue show the name of the feature class (without the button for the 'Object Class ID'), while all other properties only show a 'Not Available'.

Putting the redraw into the GetSetDataConnection method means that for every layer the map view will be redrawn. I set the redraw in there because when having it right after line 6 I am told that the redraw method must be called on the thread this object was created. Do I have to set the redraw into the GetSetDataConnection method or can I do this also at a more 'central place' where the map view is only updated once all layers got their new data source. 

- We are living in the 21st century.
GIS moved on and nobody needs a format consisting out of at least three files! No, nobody needs shapefiles, not even for the sake of an exchange format. Folks, use GeoPackage to exchange data with other GIS!
0 Kudos
RichRuh
Esri Regular Contributor

You can call Map.Redraw once, at the end of the process.  Sorry for not stating this earlier.

The Map APIs are not my area of speciality, so hopefully this will work.

Also, you probably want to also walk through the StandAloneTable collection as well as Layers, but it makes sense to get the feature layer portion working first.

--Rich

0 Kudos
TomGeo
by
Occasional Contributor III

Hmm, since the Map.Redraw(true) does not solve the issue, do you or one of you colleagues have a suggestion on how to get the data source shift working?

- We are living in the 21st century.
GIS moved on and nobody needs a format consisting out of at least three files! No, nobody needs shapefiles, not even for the sake of an exchange format. Folks, use GeoPackage to exchange data with other GIS!
0 Kudos
RichRuh
Esri Regular Contributor

I've asked my colleagues who work on the Map APIs to assist.  Sorry I couldn't help.

--Rich

0 Kudos
TomGeo
by
Occasional Contributor III

Thank you Rich! Looking forward to the suggestions of your colleagues, and I am pretty sure, the Map.Redraw is needed in the whole process.

Thomas

- We are living in the 21st century.
GIS moved on and nobody needs a format consisting out of at least three files! No, nobody needs shapefiles, not even for the sake of an exchange format. Folks, use GeoPackage to exchange data with other GIS!
0 Kudos
TomGeo
by
Occasional Contributor III

Hi Rich, do you think it's possible your colleagues who work on the Map API could have a look at it?

Bests Tom

- We are living in the 21st century.
GIS moved on and nobody needs a format consisting out of at least three files! No, nobody needs shapefiles, not even for the sake of an exchange format. Folks, use GeoPackage to exchange data with other GIS!
0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Thomas Becker‌,

 I used the following code snippet to change the data source for my feature layers:

private async void ChangeDatasource(FeatureLayer featLayer, string newGDB)
{
		await QueuedTask.Run(() =>
		{
			// provide a replacement data connection object
			CIMDataConnection updatedDataConnection = new CIMStandardDataConnection()
			{
				WorkspaceConnectionString = $"DATABASE={newGDB}",
				WorkspaceFactory = WorkspaceFactory.FileGDB,
				DatasetType = esriDatasetType.esriDTFeatureClass,
				Dataset = featLayer.Name
			};
			// the updated Data connection should look like this:
			// CustomWorkspaceFactoryCLSID: null
			// Dataset: "TestMultiPoints"
			// DatasetType: esriDTFeatureClass
			// WorkspaceConnectionString: "DATABASE=C:\\Data\\FeatureTest\\FeatureTest.gdb"
			// WorkspaceFactory: FileGDB

			// overwrite the data connection
			featLayer.SetDataConnection(updatedDataConnection);
		});
}

In my tests (using 2.6) I didn't need to refresh the map view, the content of my replacement data was immediately displayed.  

0 Kudos
TomGeo
by
Occasional Contributor III

Thanks a lot Wolfgang Kaiser‌! Your lines did it.
Adjusting the value assignment to WorkspaceConnectionString = $"DATABASE={newGDB}" was already enough, but I will stick to line 9 and 10 of your example as well.

Best regards Thomas

- We are living in the 21st century.
GIS moved on and nobody needs a format consisting out of at least three files! No, nobody needs shapefiles, not even for the sake of an exchange format. Folks, use GeoPackage to exchange data with other GIS!
0 Kudos