Can someone please tell me why my pins are not showing on the map?

iooovoltsiooovolts Member ✭✭

I am trying to populate a map with locations obtained from an API but it is proving very problematic. When I create a pin from the code behind it shows fine, but it does not show when I use xaml. I would really like to understand what I am doing wrong, thanks! The API successfully stores a longitude and latitude in the ObservableCollection and I can confirm that through debugging, it is just not represented on the map!

View

    <Grid>
        <maps:Map x:Name="ItemsSource="{Binding Locations}">
            <maps:Map.ItemTemplate>
                <DataTemplate>
                    <maps:Pin Position="{Binding Address="{Binding Name}" Label="{Binding Description}" />
                </DataTemplate>
            </maps:Map.ItemTemplate>
        </maps:Map>
    </Grid>

Code-behind

        private ITestApiService _testAPIService = new TestApiService();
        public MainPage()
        {
            InitializeComponent();
            BindingContext = new MainPageViewModel(_testAPIService);
            map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(51.507351, -0.127758), Distance.FromMiles(100)));
        }
    }

ViewModel

class MainPageViewModel
    {
        public ObservableCollection<Location> Locations { get; set; }
        private ITestApiService TestApiService{ get; set; }
  
        public MainPageViewModel(ITestApiService testApiService)
        {
            TestApiService= testApiService;
            PopulateEventMapView();
        }

        private async void PopulateEventMapView()
        {
            var events = await TestApiService.GetEvents();
            Locations = CreateLocation(events);
        }

        private ObservableCollection<Location> CreateLocation(List<Event> events)
        {
            var locations = new ObservableCollection<Location>();
            foreach (var eventItem in events)  
            {
                locations.Add(new Location(eventItem.Name, eventItem.Description, new Position(eventItem.Venue.Latitude, eventItem.Venue.Longitude)));
            }
            return locations;
        }
    }

Best Answer

Answers

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭
    edited April 15

    Your Bindings need a bit of work. I would be surprised if the code you pasted even compiled, so you are probably missing some in your copy/paste. Here is what I would expect to see.

        <Grid>
            <maps:Map x:Name="map" ItemsSource="{Binding Locations}">
                <maps:Map.ItemTemplate>
                    <DataTemplate>
                        <maps:Pin Position="{Binding Position}" Address="{Binding Name}" Label="{Binding Description}" />
                    </DataTemplate>
                </maps:Map.ItemTemplate>
            </maps:Map>
        </Grid>
    

    I assumed your Location objects had a Position property when cleaning up the Binding. If not, Bind the position with a converter from whatever you have for GPS data.

  • iooovoltsiooovolts Member ✭✭
    edited April 15

    @AdamMeaney thanks Adam! So I have made a few changes. The x:Name was there, surprised that slipped the copy and paste. I created a class called BaseViewModel and made it implement the INotifyPropertyChanged interface. Then in my MainPageViewModel I inherited the BaseViewModel. I would have imagined something like this should resolve the issue but it doesnt? Sorry if I'm being dense. Thanks in advance!

    class MainPageViewModel : BaseViewModel
            {
                private ObservableCollection<Location> _locations;
                public ObservableCollection<Location> Locations
                {
                    get => _locations;
                    set
                    {
                        if (!_locations.Equals(value))
                        {
                            _locations = value;
                            OnPropertyChanged();
                        }
                    }
                }
        
                private ITestApiService TestApiService { get; set; }
          
                public MainPageViewModel(ITestApiService testApiService)
                {
                    TestApiService = testApiService;
                    PopulateEventMapView();
                }
        
                private async void PopulateEventMapView()
                {
                    var events = await TestApiService.GetEvents();
                    _locations = CreateLocation(events);
                }
        
                private ObservableCollection<Location> CreateLocation(List<Event> events)
                {
                    var locations = new ObservableCollection<Location>();
                    foreach (var eventItem in events)  
                    {
                        locations.Add(new Location(eventItem.Name, eventItem.Description, new Position(eventItem.Venue.Latitude, eventItem.Venue.Longitude)));
                    }
                    return locations;
                }
            }
    
  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    _locations = CreateLocation(events);

    needs to be

    Locations = CreateLocation(events);

    or it won't use your OnPropertyChanged implementation.

Sign In or Register to comment.