Select to view content in your preferred language

How to save layer symbology as text and apply it later

247
6
Jump to solution
2 weeks ago
zhangjinzhou
Emerging Contributor

I have been trying to save the CIMFeatureLayer, Renderer, Symbol as text and load it later. But all failed with error like can not create instance of abstract class.

Here is an example code with CIMFeatureLayer:

var cimLayer = mapLayer.GetDefinition() as CIMFeatureLayer;
String xmlSymbology = JsonConvert.SerializeObject(cimLayer);
CIMFeatureLayer layer2 = JsonConvert.DeserializeObject<CIMFeatureLayer>(xmlSymbology);
mapLayer.SetDefinition(layer2);

 

What's the best practice for this task with ArcGIS Pro SDK?

0 Kudos
1 Solution

Accepted Solutions
GKmieliauskas
Esri Regular Contributor

Lyrx is a pure text solution - xml:

{
  "type" : "CIMLayerDocument",
  "version" : "1.1.0",
  "build" : 3219,
  "layers" : [
    "CIMPATH=map/meteoritesuk.xml"
  ],
  "layerDefinitions" : [
    {
      "type" : "CIMFeatureLayer",
      "name" : "MeteoritesUK",
      "uRI" : "CIMPATH=map/meteoritesuk.xml",
      "sourceModifiedTime" : {
        "type" : "TimeInstant"
      },
      "description" : "MeteoritesUK",
      "layerElevation" : {
        "type" : "CIMLayerElevationSurface",
        "mapElevationID" : "{D9EFA120-D6D6-4152-8711-6765DCCF05C5}"
      },
      "expanded" : true,
      "layerType" : "Operational",
      "showLegends" : true,
      "visibility" : true,
      "displayCacheType" : "Permanent",
      "maxDisplayCacheAge" : 5,
      "showPopups" : true,
      "autoGenerateFeatureTemplates" : true,
      "featureTable" : {
        "type" : "CIMFeatureTable",
        "displayField" : "NAME",
        "editable" : true,
        "dataConnection" : {
          "type" : "CIMStandardDataConnection",
          "workspaceConnectionString" : "DATABASE=.\\SDK.gdb",
          "workspaceFactory" : "FileGDB",
          "dataset" : "MeteoritesUK",
          "datasetType" : "esriDTFeatureClass"
        },
        "studyAreaSpatialRel" : "esriSpatialRelUndefined",
        "searchOrder" : "esriSearchOrderSpatial"
      },

 

View solution in original post

0 Kudos
6 Replies
GKmieliauskas
Esri Regular Contributor

Hi,

I would recommend you use Esri lyrx format to save layer and load it later. More info here.

0 Kudos
zhangjinzhou
Emerging Contributor

Hi,

Thank you for the reply! For my case, a pure text solution would be way better as it doesn't require change of existing addin architecture as all of other info are saved as a xml. In ArcMap, we had this solution

 

// Save renderer as hex
hex = SaveToHex((ESRI.ArcGIS.esriSystem.IPersistStream)(((ESRI.ArcGIS.Carto.IGeoFeatureLayer)layerObj).Renderer));

// Load renderer from hex
renderer = LoadFromHex(data);
((ESRI.ArcGIS.Carto.IGeoFeatureLayer)layerObj).Renderer = (ESRI.ArcGIS.Carto.IFeatureRenderer)renderer;

 

Is there an equivalent class of IGeoFeatureLayer in ArcGIS Pro SDK?

0 Kudos
GKmieliauskas
Esri Regular Contributor

Lyrx is a pure text solution - xml:

{
  "type" : "CIMLayerDocument",
  "version" : "1.1.0",
  "build" : 3219,
  "layers" : [
    "CIMPATH=map/meteoritesuk.xml"
  ],
  "layerDefinitions" : [
    {
      "type" : "CIMFeatureLayer",
      "name" : "MeteoritesUK",
      "uRI" : "CIMPATH=map/meteoritesuk.xml",
      "sourceModifiedTime" : {
        "type" : "TimeInstant"
      },
      "description" : "MeteoritesUK",
      "layerElevation" : {
        "type" : "CIMLayerElevationSurface",
        "mapElevationID" : "{D9EFA120-D6D6-4152-8711-6765DCCF05C5}"
      },
      "expanded" : true,
      "layerType" : "Operational",
      "showLegends" : true,
      "visibility" : true,
      "displayCacheType" : "Permanent",
      "maxDisplayCacheAge" : 5,
      "showPopups" : true,
      "autoGenerateFeatureTemplates" : true,
      "featureTable" : {
        "type" : "CIMFeatureTable",
        "displayField" : "NAME",
        "editable" : true,
        "dataConnection" : {
          "type" : "CIMStandardDataConnection",
          "workspaceConnectionString" : "DATABASE=.\\SDK.gdb",
          "workspaceFactory" : "FileGDB",
          "dataset" : "MeteoritesUK",
          "datasetType" : "esriDTFeatureClass"
        },
        "studyAreaSpatialRel" : "esriSpatialRelUndefined",
        "searchOrder" : "esriSearchOrderSpatial"
      },

 

0 Kudos
zhangjinzhou
Emerging Contributor

That's wonderful! Do you have any sample code for this? Thank you in advance!

 

0 Kudos
GKmieliauskas
Esri Regular Contributor

Savint to lyrx:

LayerDocument layerDocument = new LayerDocument(layer);
layerDocument.Save(@"c:\Data\MyLayerDocument.lyrx");

Opening from lyrx:

//Note: Call within QueuedTask.Run()
var layerDoc = new LayerDocument(@"E:\Data\SDK\Default2DPointSymbols.lyrx");
var createParams = new LayerCreationParams(layerDoc.GetCIMLayerDocument());
LayerFactory.Instance.CreateLayer<FeatureLayer>(createParams, MapView.Active.Map);

Modifying existing layer symbology using lyrx:

        private static async Task ModifyLayerSymbologyFromLyrFileAsync(FeatureLayer featureLayer, string layerFile)
        {
            await QueuedTask.Run(() => {
                //Does layer file exist
                if (!System.IO.File.Exists(layerFile))
                    return;

                //Get the Layer Document from the lyrx file
                var lyrDocFromLyrxFile = new LayerDocument(layerFile);
                var cimLyrDoc = lyrDocFromLyrxFile.GetCIMLayerDocument();

                //Get the renderer from the layer file
                var rendererFromLayerFile = ((CIMFeatureLayer)cimLyrDoc.LayerDefinitions[0]).Renderer as CIMSimpleRenderer;

                if (rendererFromLayerFile == null)
                    return;

                //Apply the renderer to the feature layer
                featureLayer?.SetRenderer(rendererFromLayerFile);

            });
        }

 

0 Kudos
zhangjinzhou
Emerging Contributor

Thank you so much!

0 Kudos