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); }
}
}
}
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);
}
}
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