Load GroupLayer in code on startup

2312
9
Jump to solution
10-14-2015 08:08 AM
ChristinaKochan1
Occasional Contributor

I have an offline .mpk that I would like to load into a GroupLayer on startup (not in xaml). I am doing this in my ViewModel. If I add the ArcGISDynamicMapServiceLayer directly to the Map.Layers, it works fine. If I add the GroupLayer first and then add the dynamic layer, it doesn't work and I get a spatial reference error. So, I tried to set the SpatialReference on the Map before adding the GroupLayer, and it works for adding the GroupLayer but then I get the spatial reference error when the dynamic layer is added. I also tried adding the dynamic layer to the GroupLayer first and then adding the GroupLayer to the Map.Layers, but that also failed and gave me the spatial reference error.

How can I add a GroupLayer containing an ArcGISDynamicMapServiceLayer on startup??

0 Kudos
1 Solution

Accepted Solutions
FreddieGibson
Regular Contributor II

You'll want to use SpatialReference.create instead of new SpatialReference. Also, the spatial reference won't be set for the map until you set the extent of the map. Below is the logic I used on my end.

public MainWindow()
{
    InitializeComponent();


    MyMapView.LayerLoaded += (sender, args) =>
    {
        Debug.WriteLine(args.Layer);
        Debug.WriteLine(args.LoadError);
    };


    MyMapView.ExtentChanged += (sender, args) => Debug.WriteLine(MyMapView.Extent);


    MyMapView.Loaded += async (sender, args) =>
    {
        string srcPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        string mpkPath = Path.Combine(srcPath, @"data\MapPackage3857.mpk");


        LocalMapService lms = new LocalMapService(mpkPath);
        await lms.StartAsync();
        ArcGISDynamicMapServiceLayer dmsLayer = new ArcGISDynamicMapServiceLayer(new Uri(lms.UrlMapService));
        //ArcGISDynamicMapServiceLayer dmxLayer = new ArcGISDynamicMapServiceLayer(new Uri("http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer"));


        BackgroundGroupLayer grpLayer = new BackgroundGroupLayer();
        //GroupLayer grpLayer = new GroupLayer();
        grpLayer.ChildLayers.Add(dmsLayer);


        Map map = new Map
        {
            SpatialReference = SpatialReference.Create(3857),
            InitialViewpoint =
                new Viewpoint(new Envelope(-20037508, -12242956, 20037508, 12242956,
                    SpatialReference.Create(3857)))
        };
                
        //map.Layers.Add(dmxLayer);
        map.Layers.Add(grpLayer);


        MyMapView.Map = map;
    };
}


public class BackgroundGroupLayer : GroupLayer
{
             
}

View solution in original post

9 Replies
FreddieGibson
Regular Contributor II

Have you tried logic similar to the following? This appears to work for me.

2015-10-14_0918.png

0 Kudos
ChristinaKochan1
Occasional Contributor

Yes, in my original post I said "I also tried adding the dynamic layer to the GroupLayer first and then adding the GroupLayer to the Map.Layers, but that also failed and gave me the spatial reference error."

The one thing I am not doing that you are is creating a new instance of Map, but I'm not sure why I would have to do that since it's a brand new map anyway. I guess I will try that and see if it helps?

Thanks

0 Kudos
ChristinaKochan1
Occasional Contributor

Hmm, apparently the problem is that I am using an extended version of the GroupLayer. If I use a straight up GroupLayer it works, but when I use my extended version it does not.

At the moment my layer is very simple, and it's just so I can pass around my specific IBackgroundGroupLayer easily throughout my code without requiring Esri references:

public class BackgroundGroupLayer : GroupLayer, IBackgroundGroupLayer

    {

        public BackgroundGroupLayer() : base()

        {

            DisplayName = "Backgrounds";

            ID = "Backgrounds";

            ShowLegend = true;

        }

    }

Is there some reason Esri would not support extending a Layer class? It's not sealed, so what's the purpose of not allowing this?

0 Kudos
ChristinaKochan1
Occasional Contributor

Another update: if I add my BackgroundGroupLayer after the regular GroupLayer, it works fine and I can add shapefiles/etc. to it. It's only when it's the first layer added that it fails.

0 Kudos
FreddieGibson
Regular Contributor II

I can replicate the same. The problem appears to be related to the Spatial Reference (sref) not being set for the view when adding the extended basemap layer. Have you noticed that when loading a GroupLayer that the sublayer is added first to set the sref, whereas adding an extended GroupLayer adds the GroupLayer first, which causes the sublayers to throw System.InavlidOperationException : The View did not obtain a spatial reference from the base layer when adding its sublayers.

If I set the spatial reference on the map directly or add a layer prior to adding the groupLayer that sets the sref of the view everything works just fine.

ChristinaKochan1
Occasional Contributor

I did try that and just set it using Map.SpatialReference = new SpatialReference(4326); before I added any layers but that didn't work for me either and I still got the sref error. Is there a better way to set the Map.SpatialReference?

0 Kudos
FreddieGibson
Regular Contributor II

You'll want to use SpatialReference.create instead of new SpatialReference. Also, the spatial reference won't be set for the map until you set the extent of the map. Below is the logic I used on my end.

public MainWindow()
{
    InitializeComponent();


    MyMapView.LayerLoaded += (sender, args) =>
    {
        Debug.WriteLine(args.Layer);
        Debug.WriteLine(args.LoadError);
    };


    MyMapView.ExtentChanged += (sender, args) => Debug.WriteLine(MyMapView.Extent);


    MyMapView.Loaded += async (sender, args) =>
    {
        string srcPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        string mpkPath = Path.Combine(srcPath, @"data\MapPackage3857.mpk");


        LocalMapService lms = new LocalMapService(mpkPath);
        await lms.StartAsync();
        ArcGISDynamicMapServiceLayer dmsLayer = new ArcGISDynamicMapServiceLayer(new Uri(lms.UrlMapService));
        //ArcGISDynamicMapServiceLayer dmxLayer = new ArcGISDynamicMapServiceLayer(new Uri("http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer"));


        BackgroundGroupLayer grpLayer = new BackgroundGroupLayer();
        //GroupLayer grpLayer = new GroupLayer();
        grpLayer.ChildLayers.Add(dmsLayer);


        Map map = new Map
        {
            SpatialReference = SpatialReference.Create(3857),
            InitialViewpoint =
                new Viewpoint(new Envelope(-20037508, -12242956, 20037508, 12242956,
                    SpatialReference.Create(3857)))
        };
                
        //map.Layers.Add(dmxLayer);
        map.Layers.Add(grpLayer);


        MyMapView.Map = map;
    };
}


public class BackgroundGroupLayer : GroupLayer
{
             
}
ChristinaKochan1
Occasional Contributor

Thank you! That did the trick.

When would be the right time to use new SpatialReference() rather than SpatialReference.Create()?

0 Kudos
FreddieGibson
Regular Contributor II

I think the expectation is that you should always use SpatialReference.Create. I used to always use the new approach until one of my colleagues made me aware of this a few months ago. This is documented on the following page:

Guidelines and best practices

https://developers.arcgis.com/net/desktop/guide/guidelines-and-best-practices.htm

2015-10-15_1408.png