Map.Clone / GroupLayer.Clone bug

328
1
11-30-2022 06:10 AM
BjørnarSundsbø1
Occasional Contributor II

Hi,

We configure multiple webmaps in portal, and we want to merge them into a new webmap that is the union of the individual maps. Customer have different teams managing the content of the different maps, which is why we are not working with a single large webmap.

We've had multiple issues related to merging the maps into one.

We've tried different solutions to merge:

  • ToJson() for each map, and perform a JSON merge to create the JSON for a new Map.FromJson()
    • For some reason we didn't get PopupDefinitions and some other properties using this technique, even when having performed map.LoadAsync() or LoadAsync for individual layers
  •  Iterate referenceLayers, OperationalLayers and BaseLayers and perform a Clone
    • Most things work, but we frequently get error message similar to
    • ArcGisMapImageLayer within a GroupLayer fail to reflect IsVisible, so the user is not able to show/hide that layer.
      • Moving them outside of a group works, but that's not particularly functional for the structure presented to the user.

Is it possible that Clone clones some references to the original CoreArcGISMapImageLayer referencing the original Map that is no longer alive?

I've tried implementing my own Clone method to do similar things to the runtime Clone, but in some situations I need to Load the source layer, which gives me the No access to this resource (or something to that effect).

 

Any suggestion for the best way to merge multiple maps into one?

Tags (3)
0 Kudos
1 Reply
BjørnarSundsbø1
Occasional Contributor II

This appears to be a bug with clone of Map.Clone() and GroupLayer.Clone(). 

The map contains two ArcGisMapImageLayer that holds two sublayers. Both sublayers are visible, while the imagelayer is not.

One imagelayer is within a GroupLayer that is visible, and the other layer is on the root of the map.

If I use Map.Clone(), I'm not able to change the visibility of the imagelayer within a grouplayer until i toggle the visibility of the grouplayer, and then change the visibility of the imagelayer

I addressed it with the following snippet:

 

private Esri.ArcGISRuntime.Mapping.Map CloneMap(Esri.ArcGISRuntime.Mapping.Map sourceMap)
{
    var targetMap = new Esri.ArcGISRuntime.Mapping.Map(sourceMap.SpatialReference)
    {
        InitialViewpoint = sourceMap.InitialViewpoint,
        MaxScale = sourceMap.MaxScale,
        MinScale = sourceMap.MinScale,
        Basemap = new Basemap()
    };
    foreach (var layer in sourceMap.OperationalLayers)
    {
        targetMap.OperationalLayers.Add(layer.CloneLayer());
    }

    if (sourceMap.Basemap != null)
    {
        foreach (var layer in sourceMap.Basemap.BaseLayers)
        {
            targetMap.Basemap.BaseLayers.Add(layer.CloneLayer());
        }

        foreach (var layer in sourceMap.Basemap.ReferenceLayers)
        {
            targetMap.Basemap.ReferenceLayers.Add(layer.CloneLayer());
        }
    }

    return targetMap;
}

 

And the CloneLayer Extension method

/// <summary>
/// Helper class for cloning of layers. There is an issue with clone of <see cref="GroupLayer"/> where the children are <see cref="ArcGISMapImageLayer"/>
/// with visibility as hidden in the original map.
/// </summary>
public static class MapCloneExtensions
{
    public static Layer CloneLayer(this Esri.ArcGISRuntime.Mapping.Layer layer)
    {
        if(layer is GroupLayer groupLayer)
        {
            return CloneInternal(groupLayer);
        }

        return layer.Clone();
    }

    /// <summary>
    /// Clone a group layer, and it's children
    /// </summary>
    /// <param name="sourceGroupLayer"></param>
    /// <returns></returns>
    private static Layer CloneInternal(GroupLayer sourceGroupLayer)
    {
        // GroupLayer.Clone() does not work with visibility, so we need to do it manually
        var groupLayer = new GroupLayer
        {
            Id = sourceGroupLayer.Id,
            Name = sourceGroupLayer.Name,
            IsVisible = sourceGroupLayer.IsVisible,
            Opacity = sourceGroupLayer.Opacity,
            MaxScale = sourceGroupLayer.MaxScale,
            MinScale = sourceGroupLayer.MinScale,
        };
        foreach(var layer in sourceGroupLayer.Layers)
        {
            groupLayer.Layers.Add(CloneLayer(layer));
        }

        return groupLayer;
    }
}
0 Kudos