ApplySymbologyFromLayer GeoProcessing Tool

1032
30
Jump to solution
06-19-2019 11:09 AM
Highlighted
Regular Contributor

Hi,

I'm trying to update the layers of a map by running the ApplySymbologyFromLayer GeoProcessing tool through some .NET code.  For a while, there was a reported BUG-000106281 about this, but it is apparently fixed in 2.3.

But.....I still cannot get it to work.  Is there something wrong with my code?  All of my .lyr files are located on a network drive.  I get a NULL Reference Exception at the .ExecuteToolAsync line.

Thanks,

                Map map = MapView.Active.Map;

pBar.Minimum = 0;
pBar.Maximum = map.Layers.Count;

this.Cursor = Cursors.Wait;

GPExecuteToolFlags flags = GPExecuteToolFlags.GPThread;

foreach (Layer layer in map.GetLayersAsFlattenedList().OfType<FeatureLayer>())
{
var gpresult = await Geoprocessing.ExecuteToolAsync("ApplySymbologyFromLayer_management", new string[] { layer.Name.ToString(), @"K:\DSM Shared\ArcMap Symbology\10.2 Schema\Editing Symbols\" + layer.Name.ToString() + ".lyr" }, null, null, flags);
pBar.Value = pBar.Value + 1;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Tags (2)
Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Esri Regular Contributor

Hi Brian

Pro 2.4 allows you to apply symbology from a layer file using the Pro .NET API.  A new LayerDocument class at 2.4 provides this functionality. 

Pro 2.4 will be released this week. Using Pro 2.4, the snippet below will apply symbology from a lyr file to a feature layer in the TOC.

private static async Task ModifyLayerSymbologyFromLyrFileAsync(IEnumerable<FeatureLayer> featureLayers, string layerFile)
{
await QueuedTask.Run( () => {
foreach (var featureLayer in featureLayers)
{
//Get the Layer Document from the lyrx file
var lyrDocFromLyrxFile = new LayerDocument(layerFile);
var cimLyrDoc = lyrDocFromLyrxFile.GetCIMLayerDocument();

//Get the renderer from the layer file
//This lyr file has a unique value renderer.
var rendererFromLayerFile = ((CIMFeatureLayer)cimLyrDoc.LayerDefinitions[0]).Renderer as CIMUniqueValueRenderer;

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

});
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Thanks

Uma

View solution in original post

30 Replies
Highlighted
Esri Notable Contributor

Maybe somebody in the ArcGIS Pro SDK‌ space could look since the question is about the code.

Reply
0 Kudos
Highlighted
Regular Contributor

I got it moved....thanks!

Highlighted
Esri Regular Contributor

Brian,

Could be the cancellation source. Ive never had luck setting it to null and always specify a typed variable if needed.

      //create feature class from template
var mva = Geoprocessing.MakeValueArray(@"C:\arcgis\ArcTutor\Editing\Zion.gdb", "test", "POINT",@"C:\arcgis\ArcTutor\Editing\Zion.gdb\Ranger_stations");
var cts = new System.Threading.CancellationTokenSource();
var result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", mva, null, cts.Token,null,GPExecuteToolFlags.None);‍‍‍‍

If I didn't need to specify the GP flags i would just have the tool name and the value array like so:

mva = Geoprocessing.MakeValueArray(tablePath, "Layer", "STRING");
await Geoprocessing.ExecuteToolAsync("AddField_management", mva);
Reply
0 Kudos
Highlighted
Regular Contributor

Hi Sean Jones‌,

That is definitely helping and now I can get through the code with no errors, but....the symbology (from the layer file) still does not get applied.  

I've tested using some hard coded values.  When I  use the Apply Symbology tool in ArcPro and use the same layer/layer file combination, it works.  But when doing it through code it doesn't.  No errors.....just no results.  The original symbology is still there.

I've tried with both .lyr and .lyrx files.

Any ideas??

                    var mva = Geoprocessing.MakeValueArray("GISWRKS1.WORKS.WAT_Hydrant", @"K:\DSM Shared\ArcMap Symbology\TEST\Editing Symbols\GISWRKS1.WORKS.WAT_Hydrant.lyrx");
var gpresult = await Geoprocessing.ExecuteToolAsync("ApplySymbologyFromLayer_management", mva);
Highlighted
Regular Contributor

Hi Brian,

Have you tried to set GPExecuteToolFlags flags = GPExecuteToolFlags.GPThread;

More info here: https://community.esri.com/thread/198403-pro-20-bug-apply-symbology-from-layer-geoprocessing-tool

Highlighted
Regular Contributor

Hi Gintautas Kmieliauskas‌,  

Great, thanks!  Things are working even better now.  I can apply symbology through the code now, but it only works some of the time.  If I only have one layer in my map, it works.  But with multiple layers I run into problems.  See example screenshots below, and the code is at the very bottom.

1.  I add layers.  They get the default symbology.

2.  I want to apply custom symbology, so I click on my "Map Symbology" tool, pick a symbology ("Edit" in this case), and then click 'Symbolize'.  The code runs, but only some of the layers get symbolized.  

3.  Only 2 of the 4 layers get the symbology applied.  In the window I can see the name of each layer as it loops through them, and all 4 are hit, but only 2 get changed.  The required 4 .lyr files are located in the network path in the code.

4.  I then manually use the Apply Symbology from Layer GP Tool, to update the other layers.  Basically doing the same thing that my the code should be doing.  Manually it works.

Any ideas as to why this only works sometimes and not all the time??

Here is the code.  It's a very simple loop.

namespace SymbologyTool_ArcPro
{
/// <summary>
/// Interaction logic for wdwSymbology.xaml
/// </summary>
public partial class wdwSymbology : ProWindow
{
public wdwSymbology()
{
InitializeComponent();
}

async private void btnSymbolize_Click(object sender, RoutedEventArgs e)
{
try
{
Map map = MapView.Active.Map;

pBar.Minimum = 0;
pBar.Maximum = map.Layers.Count;

this.Cursor = Cursors.Wait;

GPExecuteToolFlags flags = GPExecuteToolFlags.GPThread;

foreach (Layer layer in map.GetLayersAsFlattenedList().OfType<FeatureLayer>())
{
lblLayerName.Content = layer.Name.ToString();
var mva = Geoprocessing.MakeValueArray(layer.Name.ToString(), @"K:\DSM Shared\ArcMap Symbology\10.2 Schema\Editing Symbols\" + layer.Name.ToString() + ".lyr");
var gpresult = await Geoprocessing.ExecuteToolAsync("ApplySymbologyFromLayer_management", mva, null, null, null, flags);

pBar.Value = pBar.Value + 1;
}
}

catch (Exception ex)
{
ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(ex.ToString());
}

finally
{
this.Cursor = Cursors.Arrow;
MessageBox.Show("DONE");
this.Close();
}
}
}
}
Reply
0 Kudos
Highlighted
Regular Contributor

Hi Brian,

 I have had refreshing problems with symbolizing when using more complicated symbolization (symbol rotation, few different fields and etc.) 

Have you tried refresh unsuccessful symbolized layers from layer property in TOC?

1. In opened layer properties select Cache page.

2. In Cache page press "Clear Cache".

3. After that choose "Don't cache any data locally". Press OK.

If it helps then you need to change your way and do not use ApplySymbologyFromLayer_management.

1. Remove existing layer

2. Create layer from lyr file

3. Update data source to removed layer path.

4.Clear cache

It sounds strange but I use that workaround from the beginning.

More info here:

https://community.esri.com/thread/198403-pro-20-bug-apply-symbology-from-layer-geoprocessing-tool

Reply
0 Kudos
Highlighted
Regular Contributor

Hi Gintautas Kmieliauskas‌,

Yes, I remember seeing that before, but removing and re-adding layers doesn't seem like a solution.  More of a work-around to fix something that isn't working.

Sean Jones‌:  Is there a bug with ApplySymbologyFromLayer in .NET??  I just want to figure out what I need to do moving forward.

Thanks,

Reply
0 Kudos
Highlighted
Regular Contributor

Try this:

protected override async void OnClick()
{
      Map map = MapView.Active.Map;

      List<FeatureLayer> featLayers = map.GetLayersAsFlattenedList().OfType<FeatureLayer>().ToList();
      FeatureLayer inputLayer = featLayers[0];  // the first layer will be updated with symbology

      // Note: the layer file must have an extension of lyrx

     // 

      string symbologyLayer = @"D:\ProSDKall\ApplySymbology\MyProject1\Stars.lyrx";


      var parameters = Geoprocessing.MakeValueArray(inputLayer, symbologyLayer);

      IGPResult pGPresult = await Geoprocessing.ExecuteToolAsync("management.ApplySymbologyFromLayer",       parameters);


      await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
            map.Redraw(true)    // this should redraw the layer with new symbology
      );
}

To apply symbology from another layer in the Map, such as the second layer, get that layer as:

FeatureLayer symbLayer = featLayers[1];   // symbology layer

FeatureLayer inputLayer = featLayers[0];    // this layer's symbology will be updated with featLayers[1]'s symbology

* Message me personally if you are still having problem