Select to view content in your preferred language

esritoolkit:BasemapGallery - AvailableBasemaps customization does not work

1527
10
Jump to solution
02-02-2023 06:18 AM
ViktorSafar
Frequent Contributor

I have got a WPF MVVM app where I have a MapView, and the BasemapGallery from the toolkit:

 

        <esri:MapView 
            x:Name="MainMapView" 
            Map="{Binding Map}"
            />

        <esritoolkit:BasemapGallery
            x:Name="BasemapGallery"   
            GeoModel="{Binding ElementName=MainMapView, Path=Map}"
            AvailableBasemaps="{Binding AvailableBasemaps}"/>

 

The Map property on the VM:

 

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


// initialized in VM constructor
Map = new Map
{
	InitialViewpoint = new Viewpoint(new MapPoint(X, Y, spatialReference: SpatialReference.Create(3857)), 130617),
	Basemap = new Basemap(BasemapStyle.ArcGISTopographic)
};

 

Changing the mapview's base map from the gallery works fine. The gallery loads base maps from AGOL which is something I would like to override. The app will be on an offline device so I have some map packages locally but I am currently testing with a VectorTileServer base map:

 

var vectorTiledLayer = new ArcGISVectorTiledLayer(new Uri("https://server/arcgis/rest/services/MyService/VectorTileServer"));
var newBaseMap = new Basemap(vectorTiledLayer)
var item = await BasemapGalleryItem.CreateAsync(newBaseMap);
AvailableBasemaps = new List<BasemapGalleryItem>();
AvailableBasemaps.Add(item);


// where AvailableBasemaps is:
private IList<BasemapGalleryItem> _availableBasemaps;
public IList<BasemapGalleryItem> AvailableBasemaps
{
	get { return _availableBasemaps; }
	set { SetProperty(ref _availableBasemaps, value); }
}

 

The gallery is still showing the AGOL base maps, and not at all my custom base map.

What am I doing wrong?

 

Esri.ArcGISRuntime.WPF v100.15.0

Esri.ArcGISRuntime.Toolkit v100.15.0

0 Kudos
10 Replies
ViktorSafar
Frequent Contributor

If anyone's using Prism, there is a dead simple way to make your own gallery

 

XAML:

 

 

<UserControl x:Class="MapGallery.MapGalleryUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <ListView
        ItemsSource="{Binding AvailableMaps}"
        SelectedValue="{Binding SelectedMap}"        
        >
        <ListView.ItemTemplate>
            <DataTemplate>
                <WrapPanel>
                    <Image Source="{Binding Thumbnail}" Height="100" Width="100" />
                    <Label Content="{Binding Basemap.Name}" VerticalContentAlignment="Center"/>
                </WrapPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</UserControl>

 

 

 

VM:

 

 

internal class MapGalleryVM : BindableBase
{
	private readonly IEventAggregator _eventAggregator;

	public MapGalleryVM(IEventAggregator eventAggregator)
	{
		_eventAggregator = eventAggregator;
		_eventAggregator.GetEvent<BasemapsLoadedEvent>().Subscribe(HandleBasemapsLoadedEvent);
	}

	private void HandleBasemapsLoadedEvent(List<AppBasemap> appMaps)
	{
		var results = appMaps.Select(x => new MapGalleryModel()
		{
			Basemap = x.Basemap,
			Thumbnail = new BitmapImage(new System.Uri(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, x.MapFileConfig.Thumbnail)))
		});

		_ = Application.Current.Dispatcher.BeginInvoke(() =>
		{
			AvailableMaps = new ObservableCollection<MapGalleryModel>(results);
		});
	}

	private ObservableCollection<MapGalleryModel> _availableMaps;
	public ObservableCollection<MapGalleryModel> AvailableMaps
	{
		get { return _availableMaps; }
		set { SetProperty(ref _availableMaps, value); }
	}


	private MapGalleryModel _selectedMap;
	public MapGalleryModel SelectedMap
	{
		get { return _selectedMap; }
		set 
		{ 
			if (value != SelectedMap)
			{
				SetProperty(ref _selectedMap, value);
				_eventAggregator.GetEvent<BasemapChangedEvent>().Publish(value.Basemap);
			}
		}
	}
}

 

 

 

The events

 

 

internal class BasemapChangedEvent : PubSubEvent<Basemap>
{
}

internal class BasemapsLoadedEvent: PubSubEvent<List<AppBasemap>>
{
}

public class AppBasemap
{
	public Basemap Basemap { get; set; }
	public MapFileConfig MapFileConfig { get; set; }
}

 

 

where MapFileConfig is just a holder for paths to the maps and thumbnails.

 

And wherever you handle your Map:

 

 

internal class MainMapVM : BindableBase
{
	public MainMapVM(IEventAggregator eventAggregator)
	{
		_eventAggregator.GetEvent<BasemapChangedEvent>().Subscribe(HandleBasemapChangedEvent);
		LoadBasemaps().Await();
	}

 
	private void HandleBasemapChangedEvent(Basemap obj)
	{
		Map.Basemap = obj;
	}

	private async Task LoadBasemaps()
	{
		var appBasemaps = await _layerProvider.GetAppBasemaps(_isOnline);

		Map.Basemap = appBasemaps.First().Basemap;			
		_eventAggregator.GetEvent<BasemapsLoadedEvent>().Publish(appBasemaps);
	}

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