Select to view content in your preferred language

ArcGISVectorTiledLayer not showing when assigned to Map in async method

442
2
09-29-2022 02:49 AM
ViktorSafar
Frequent Contributor

I have a WPF app using MVVM/Prism and .NET Runtime SDK.

Simple VM with a Map property which is bound to a MapView.Map in the control. I am adding 2 layers to the Map's base layers collection. I am adding a `ArcGISMapImageLayer` and a `ArcGISVectorTiledLayer`.

When I assign the layers in the VM constructor, everything works fine. When I assign the layers in an async method called from the constructor (via fire and forget), only the `ArcGISMapImageLayer` gets shown in the MapView when the UI lods, not the `ArcGISVectorTiledLayer`. I've played with it a lot, changing order of addition, explicitly calling it on the UI thread, but it all behaves the same when the layers are added in an async method.

The reason for an async method is that I want to load the layers but have removed the extra code for clarity. The SetupLayers() method is commented out on purpose in the given snippet. When the constructor calls it, the problem occurs.

 

 

 

namespace NFS_POC.Views
{
    internal class MainMapVM : BindableBase
    {
        public MainMapVM()
        {

            Map = new Map
            {
                InitialViewpoint = new Viewpoint(59, 6, 1000000)
            };

    
            // SetupLayers();

 

            // this works fine
            var imageLayer = new ArcGISMapImageLayer(new Uri("https://services.server.tld/arcgis/rest/services/something/something2/MapServer"));
            Map.Basemap.BaseLayers.Add(imageLayer);

 

            // this works fine
            var vectorTiledLayer = new ArcGISVectorTiledLayer(new Uri("https://services.server.tld/arcgis/rest/services/foo/bar/VectorTileServer"));
            Map.Basemap.BaseLayers.Add(vectorTiledLayer);        
        }

        private async Task SetupLayers()
        {
            // this works fine
            var imageLayer = new ArcGISMapImageLayer(new Uri("https://services.server.tld/arcgis/rest/services/something/something2/MapServer"));
            Map.Basemap.BaseLayers.Add(imageLayer);

 

            // this does not work???
            var vectorTiledLayer = new ArcGISVectorTiledLayer(new Uri("https://services.server.tld/arcgis/rest/services/foo/bar/VectorTileServer"));
            Map.Basemap.BaseLayers.Add(vectorTiledLayer);
        }
 

        private Map _map;
        public Map Map
        {
            get { return _map; }
            set { SetProperty(ref _map, value); }
        }        
    }
}

 

 

 

 
0 Kudos
2 Replies
JoeHershman
MVP Regular Contributor

One thing you are not doing is calling .LoadAsync().  Personally I don't like directly calling a async method from a constructor.  The way I do something similar.  Create a simple event LoadMapEvent

public MainWindowViewModel(IEventAggregator eventAggregator)
{
	//Allow async for loading map
	eventAggregator.GetEvent<LoadMapEvent>().Subscribe(OnLoadMap);

	eventAggregator.GetEvent<LoadMapEvent>().Publish();
}

private async void OnLoadMap()
{
	try
	{
		//add layers
		await Map.LoadAsync();
	}
	catch (Exception e)
	{
		_log?.Error(e, e.Message);
	}
}

 

Thanks,
-Joe
0 Kudos
ViktorSafar
Frequent Contributor

Yeah, agreed that calling an async method from a constructor is not a good design. I am in a recon/play mode trying to see what the framework can do.

However, I would argue that you're basically doing the same. The event aggregator is fire and forget

0 Kudos