1

Kia ora StackOverFlow,

I'm creating a Google Maps page which has numerous bindings (I used Google Maps bindings). An example of this bindings is a pin bindings - as you will see below:

XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" 
             xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
             x:Class="standard.MainPage">

    <StackLayout>
        <maps:Map VerticalOptions="FillAndExpand"
                  MyLocationEnabled="True">
            <maps:Map.Behaviors>
                <bindings:BindingPinsBehavior Value="{Binding Pins}" />
            </maps:Map.Behaviors>
        </maps:Map>
    </StackLayout>

</ContentPage>

ViewModel:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms.GoogleMaps;
using Xamarin.Forms.GoogleMaps.Bindings;

namespace standard.ViewModels
{
    public class MainPageViewModel : BaseViewModel
    {

       private ObservableCollection<Pin> _pins;
        public ObservableCollection<Pin> Pins
        {
            get => _pins;
            set
            {
                _pins = value;
                RaisePropertyChanged();
            }
        } 

        public MainPageViewModel()
        {
            Pins = new ObservableCollection<Pin>();

            Pins.Add(new Pin()
            {
                Type = PinType.Place,
                Position = new Position(78,77)
            });
                
        }
    }
}

Xaml.CS:

using standard.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.GoogleMaps;

namespace standard
{
    public partial class MainPage : ContentPage
    {
        public MainPageViewModel MainPageViewModel;
        public MainPage()
        {
            InitializeComponent();

            this.BindingContext = MainPageViewModel = new MainPageViewModel();
        }
    }

Now - the problem is - I've set the BindingContext as expected but the pin is NOWHERE to be seen on the map.

It's important that I can see the pins on the map because I am making an app in which the user needs to see the location of the event/party. I also want a solution in an MVVM approach.

(using Android lollipop)

Where it should be on the map enter image description here

image

enter image description here This is my problem.

Thank you,

Kia pai to ra

Have a great day

Edit: Thank you to Leo Zhu who kind of solved my question - I am looking for an MVVM-based solution for now but thank you anyways

Things I've tried Result
Tried to set the Binding of the pins using the default maps item template. Still did not work or show on the map
Tried to call OnPropertyChanged after adding an item to the observable collection Still the pin did not show on the map
Tried using a Pin instead of an ObservableCollections of Pins Still the Pin was nowhere to be seen on the map
Tried setting the BindingContext of the map itself to the MainPageViewModel Still the Pin is nowhere to be seen
Tried to use an earlier update of the Google Maps Binding NuGet package Still - you guessed it - I cannot see the pin
  • do you know where 78,77 is on the map? Hint - it's not anywhere on your screenshot – Jason Dec 07 '20 at 02:00
  • Yes @Jason I've searched the entire map and it's not there. Would you like to add anything else? –  Dec 07 '20 at 02:44
  • What about ```RaisePropertyChanged(nameof(Pins));``` after add one pin? – Shaw Dec 07 '20 at 03:35
  • I will try it tomorrow - thanks @Shaw (nameof is not needed as I am using the 'CallerMemberName' attribute) –  Dec 07 '20 at 05:42
  • Or add CollectionChaged event in [this queation](https://stackoverflow.com/questions/1427471/observablecollection-not-noticing-when-item-in-it-changes-even-with-inotifyprop). Anyway, add an item to a collection won't evoke the propertychanged of a collection. – Shaw Dec 07 '20 at 07:30
  • Yes I know but it should register in the maps itself with the code mentioned in the question - I'm following a course on Pluralsight in the Advanced section on how to integrate google Maps - all code mentioned above has been shown to work on the course creator's computer. If you want to check out the course it's called Google Maps in Xamarin.Forms on Pluralsight. So it's strange it's not working - because on the author's computer (with the exact same code) it worked perfectly. –  Dec 07 '20 at 08:26
  • @tommy99 how does your xaml.cs file look like? I assume the bindings are being properly set. – SomeStudent Dec 07 '20 at 20:32
  • Yes they are properly set @SomeStudent, I will show you an example –  Dec 07 '20 at 20:33
  • Not sure if this would work, but, what if you set an x:name on the and then in your main page where youset the binding context, do {NameYouGaveInx:Name}.BindingContext = MainPageViewModel. If that won't work, then go with Zhao's approach, whilst it is not maybe 100% MVVM, it will still let you proceed – SomeStudent Dec 07 '20 at 20:44
  • Tried that but it still isn't working whatsoever –  Dec 07 '20 at 20:51

2 Answers2

1

Please do not initialize ObservableCollection<Pin> Pins.

MainPageViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms.GoogleMaps;
using Xamarin.Forms.GoogleMaps.Bindings;

namespace standard.ViewModels
{
    public class MainPageViewModel : BaseViewModel
    {

       public ObservableCollection<Pin> Pins { get; set; }

        public MainPageViewModel()
        {
            
        }

        internal void AddPins()
        {
            Pins?.Add(new Pin()
            {
                Label = $"Pin1",
                Position = new Position(78, 77)
            });
        }
    }
}

Xaml.CS:

using standard.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.GoogleMaps;

namespace standard
{
    public partial class MainPage : ContentPage
    {
        public MainPageViewModel MainPageViewModel;
        public MainPage()
        {
            MainPageViewModel = new MainPageViewModel();
            this.BindingContext = MainPageViewModel;
            InitializeComponent();
            MainPageViewModel.AddPins();
            
        }
    }
}
Jai Gupta
  • 1,374
  • 9
  • 8
  • Thank you very much @jai for the solution - it worked very well! (in 5 hrs I can award the reputation) –  Dec 09 '20 at 19:41
0

I meet the same issue, and one workaround was not to add a Pin in the viewModel's constructor, but in page.xaml.cs, as follows:

<maps:Map VerticalOptions="FillAndExpand" x:Name = "myMap"
              MyLocationEnabled="True">
  <maps:Map.Behaviors>
     <bindings:BindingPinsBehavior Value="{Binding Pins}" />
  </maps:Map.Behaviors>
</maps:Map>

public MapPage()
    {
        InitializeComponent();
        myMap.Pins.Add(new Pin
        {
            Label = $"Pin1",
            Position = new Position(78, 77)
        });
    }
Leo Zhu
  • 15,726
  • 1
  • 7
  • 23