Maps, Current Location & Xaml

I wouldn't think that I'm the first to ask this.... but how can you set the current location in Xaml while using a View Model? I've searched & found out that I have to use an external GeoLocator (XLabs) & then the only way I'm seeing how to set the current location in the map is through code behind. Is this correct?

Steve.

Tagged:

Answers

  • SteveTriano.6618SteveTriano.6618 USMember

    Really...nobody has any clues on this? Am I the only one to wonder this?

  • AndrewMobileAndrewMobile USMember ✭✭✭✭
    edited May 2015

    Yes, here's one way to use IGeoLocator from XLabs in your view-model.
    The code gets coordinates when view corresponding to the view-model becomes visible and it subscribes to position error handler

    public class YourViewModel : XLabs.Forms.Mvvm.ViewModel
    {
            IGeolocator _geoLocator;
    
            public YourViewModel()
            {
                    _geoLocator = DependencyService.Get<IGeolocator> ();
            }
    
                  // note that your View must derive from XLabs.Forms.Mvvm.BaseView in order for this method to be called for the view-model
                   async public override void OnViewAppearing()
                   {
                            _geoLocator.PositionError += OnListeningError;
                           Position position = await _geoLocator.GetPositionAsync(TimeSpan.FromMiliseconds(5000));
                    }
    
                  // note that your View must derive from XLabs.Forms.Mvvm.BaseView in order for this method to be called for the view-model
                   async public override void OnViewDisappearing()
                   {
                        _geoLocator.PositionError -= OnListeningError;
                   }
    
                  private void OnListeningError(object sender, PositionErrorEventArgs e)
                  {
                        // handle error...
                  }
    }
    

    About setting the location in the Map:
    Map doesn't have a bindable property for position, so you need to call map.MoveToRegion(MapSpan).
    To do this from view-model, they are few ways:

    1.- in the view, you can subscribe to the _geoLocator position changed like you did in the view-model

    2.- send a message with MessageCenter from view-model to view: http://developer.xamarin.com/guides/cross-platform/xamarin-forms/messaging-center/ http://code.tutsplus.com/tutorials/an-introduction-to-xamarinforms-and-messaging--cms-22526

    3.- in the view-model you can have a propertylike like:

      IGeoLocationListener GeoLocationListener   { get; set;  }
    

    the view-model will call

      GeoLocationListener.Position = position 
    

    IGeoLocationListener is a simple interface which view implements

      public interface IGeoLocationListener {  Position Position { set; } } 
    

    in the OnAppearing override in your view class, you call

     (ViewModel as MyViewModel).GetLocationListener = this;
    

    and in the OnDisappearing you clear it

     (ViewModel as MyViewModel).GeoLocationListener  = null;
    

    4.- You can create an attached property to the Map to which you can bind to the view-model.

    Hope this answers your question.

  • SteveTriano.6618SteveTriano.6618 USMember

    Excellent thanks I'll give this a shot!

  • SteveTriano.6618SteveTriano.6618 USMember

    Andrei,

    What kind of response time should I expect from this Geolocator? When I run this... it takes at least 30 seconds to get the current location & I haven't implemented the message center yet.

    Would it be better to use the Dependency Service & get at the native map & geolocator?

  • AndrewMobileAndrewMobile USMember ✭✭✭✭

    what do you mean by response? GeoLocator gets you a Position instance.

  • SteveTriano.6618SteveTriano.6618 USMember

    So basically what I'm after is this.... I want my user to open a page that shows their current location. I would think this would be very simple.

    When I say response... I'm referring to getting the current location from the GeoLocator like;
    https://github.com/XLabs/Xamarin-Forms-Labs/wiki/Geolocator

    Thanks for your responses Andrei. This is my first mobile only project so I'm still learning.

  • AndrewMobileAndrewMobile USMember ✭✭✭✭

    this line from the code I posted above gives you the position:
    Position position = await _geoLocator.GetPositionAsync(TimeSpan.FromMiliseconds(5000));

    it takes at least 30 seconds to get the current location & I haven't implemented the message center yet.

    Does it take 30 seconds for the await call to return?

  • SteveTriano.6618SteveTriano.6618 USMember

    So your statement doesn't pass compile....'The best overloaded method match for .... has some invalid arguments.... Argument '#1' cannot convert Timespan expression to type int. Interesting though...I add in a convert.toint32() and it still dies.

  • SteveTriano.6618SteveTriano.6618 USMember

    So if I change your line just to have 5000 then it runs & it takes 6 seconds which is better than the other option... but still that's pretty slow to load a page.

  • AndrewMobileAndrewMobile USMember ✭✭✭✭

    You are right, my code example might have a small error. The timeout is not a TimeSpan.
    Pay attention to the argument types, that should be pretty easy.

  • SteveTriano.6618SteveTriano.6618 USMember

    Are there any faster options that what's here? 6 seconds to load a page of your current location is a bit much.

  • NielsCupNielsCup NLMember ✭✭✭
    edited June 2015

    For Windows Phone 8 the _geoLocator is always null in _geoLocator = DependencyService.Get<IGeolocator> ();
    I have downloaded the XLabs project and I experience the same issue. Does anybody else have the same issue?

    EDIT: Never mind, I finally found the answer here (and I can't delete this post...)

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For Windows Phone 8.1, I am also getting _geolocator as null in _geolocator = DependencyService.Get<IGeolocator>();

    In Windows Phone 8.1 project, I have registered IGeolocator

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am my missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For Windows Phone 8.1, I am also getting null for _geolocator = DependencyService.Get<IGeolocator>();

    I have registered the IGeolocator in below method.

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am I missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For WindowsPhone 8.1, I am getting null in _geolocator = DependencyService.Get<IGeolocator>();

    Also, registered IGeolocator

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register<ISecureStorage, SecureStorage>() .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am I missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For WindowsPhone 8.1, I am getting null in _geolocator = DependencyService.Get<IGeolocator>();

    Also, registered IGeolocator

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register<ISecureStorage, SecureStorage>() .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am I missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For Windows Phone 8.1, I am also getting _geolocator as null in _geolocator = DependencyService.Get<IGeolocator>();

    In Windows Phone 8.1 project, I have registered IGeolocator

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am my missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For Windows Phone 8.1, I am also getting null for _geolocator = DependencyService.Get<IGeolocator>();

    I have registered the IGeolocator in below method.

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am I missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For WindowsPhone 8.1, I am getting null in _geolocator = DependencyService.Get<IGeolocator>();

    Also, registered IGeolocator

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register<ISecureStorage, SecureStorage>() .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am I missing something?

  • Kanchan.4505Kanchan.4505 USMember

    NielsCup,

    For WindowsPhone 8.1, I am getting null in _geolocator = DependencyService.Get<IGeolocator>();

    Also, registered IGeolocator

    private void SetIoC() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppWP(); app.Init(this); var documents = app.AppDataDirectory; resolverContainer.Register<IDevice>(t => WindowsPhoneDevice.CurrentDevice) .Register<IDependencyContainer>(t => resolverContainer) .Register<IXFormsApp>(app) .Register<ISecureStorage, SecureStorage>() .Register < XLabs.Platform.Services.Geolocation.IGeolocator, XLabs.Platform.Services.Geolocation.Geolocator>() ; Resolver.SetResolver(resolverContainer.GetResolver()); }

    Am I missing something?

  • NielsCupNielsCup NLMember ✭✭✭

    Try registering your geolocator like this: DependencyService.Register<Geolocator> ();

  • GaryMcGheeGaryMcGhee AUMember ✭✭

    Even once you have a location - it seems ridiculous but true that unless you create the map control in code (not xaml) you lose the ability to instantly begin at a given location. The constructor sets some location, and then the only way to change it is MoveToRegion which takes several seconds to "fly" there. Am I missing something?

    Is there a way to make MoveToRegion instant?

    Can we set VisibleRegion after creation?

    Come on Xamarin, this maps control needs and deserves some serious development.

    p.s. There is a hack here : http://adventuresinxamarinforms.com/tag/xamarin-forms-maps/ PositionMap() that I think is trying to get an instant transition by calling it twice.

  • balavanvigneshbalavanvignesh Member
    edited February 1

    Use Xamarin.Forms.GoogleMaps.Bindings Nuget Package for results.
    Its the best solution for MVVM structure and use xamarin.essentials package forgetting current location.

Sign In or Register to comment.