0
votes

I am trying to manipulate a Xamarin forms map , written in XAML. I would like to change the map type on click, using the command property on my button object. My code behind is in a separate cs file called MapViewModel.

Here is my View in XAML

<Grid.BindingContext>
  <mvm:MapViewModel/>
</Grid.BindingContext>
<Grid.RowDefinitions>

<Button
    HorizontalOptions="Start"
    Text="Map Types"
    Command="{Binding MapTypeChange}"
    CommandParameter="{x:Reference Name=map}"
    BackgroundColor="Olive"/>

<Button
   HorizontalOptions="Center"
   Text="Report NoShows"
   Command="{Binding SendLocationCommand}"
   CommandParameter="{x:Reference Name=MapView}"
   BackgroundColor="Red"
   />

<Button
    Text="Sync"
    Command="{Binding SyncLocationCommand}"
    CommandParameter="{x:Reference Name=MapView}"
    BackgroundColor="Green"
    />


<StackLayout
    Padding="5,50,5,0">
    <maps:Map
       Grid.Column="1"
       Grid.Row="0"
       WidthRequest="350"
       HeightRequest="500"
       x:Name="XamlMap"
       IsShowingUser="true"
       MapType="Hybrid" />
</StackLayout>
</Grid>

And here is my MapViewModel

public class MapViewModel : INotifyPropertyChanged
{
    private ActionCommand _sendlocationcommand;
    public ActionCommand SendLocationCommand
    {
        get
        {
            if (_sendlocationcommand == null)
            {
                _sendlocationcommand = new ActionCommand(SendEmailLocation);
            }
            return _sendlocationcommand;
        }
    }

    private ActionCommand<Page> _synclocationcommand;
    public ActionCommand<Page> SyncLocationCommand
    {
        get
        {
            if (_synclocationcommand == null)
            {
                _synclocationcommand = new ActionCommand<Page>(SyncLocation);
            }
            return _synclocationcommand;
        }
    }

    private ActionCommand<Map> _maptypecommand;
    public event PropertyChangedEventHandler PropertyChanged;

    public ActionCommand<Map> MapTypeCommand
    {
        get
        {
            if (_maptypecommand == null)
            {
                _maptypecommand = new ActionCommand<Map>(MapTypeChange);
                // OnPropertyChanged("MapTypeCommand");

            }
            return _maptypecommand;
        }
    }


    //**Here is where I want to  manipulate the map**
    private async void MapTypeChange(Map map)
    {
        if (map != null)
            map.MapType = MapType.Satellite;
        var locator = CrossGeolocator.Current;
        var currentPos = await locator.GetPositionAsync(timeoutMilliseconds: 10000);

        map.MoveToRegion(MapSpan.FromCenterAndRadius(
            new Xamarin.Forms.Maps.Position(currentPos.Latitude, currentPos.Longitude), Distance.FromMiles(1)));
    }

    private async void SyncLocation(Page page)
    {
        var locator = CrossGeolocator.Current;
        if (locator.IsGeolocationAvailable && locator.IsGeolocationEnabled)
        {
            locator.DesiredAccuracy = 50;
            var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
            string currentposition = ($"{position.Timestamp.UtcDateTime}");
            string latitude = ($"Latitude:  {position.Latitude}");
            string longitutde = ($" {position.Longitude}");
            string latlngposition = ($"{latitude},  {longitutde}");
            string cancel = "Cancel";
            await page.DisplayAlert($"Synchronizing .. Please wait... :{currentposition}", $"{latlngposition}", $"{cancel}");
            double lat = position.Latitude;
            double lng = position.Longitude;
        }
        else if (!locator.IsGeolocationEnabled)
        {
            await page.DisplayAlert("Device Location Error :", "Is location on ? Location is off or unavaliable please check this, and restart the application", "Exit");
            throw new ArgumentException("Device location not found, or unavalible,");
        }

    }

    private async void SendEmailLocation()
    {
        var locator = CrossGeolocator.Current;
        if (locator.IsGeolocationAvailable && locator.IsGeolocationEnabled)
        {
            var emailmessagebuilder = CrossMessaging.Current.EmailMessenger;
            locator.DesiredAccuracy = 50;
            var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
            string currentposition = ($"Date & Time : {position.Timestamp.UtcDateTime}");
            string latitude = ($"Latitude:  {position.Latitude}");
            string longitutde = ($"Longitude: {position.Longitude}");
            string latlngposition = ($"Latitude :{latitude},  Longitutde :{longitutde}, {currentposition}");

            if (emailmessagebuilder.CanSendEmail)
            {
                var email = new EmailMessageBuilder()
                    .To("")
                    .Cc("")
                    .Bcc(new[] { "", "" })
                    .Subject("")
                    .Body($"{latlngposition}")
                    .Build();
                emailmessagebuilder.SendEmail(email);
            }
        }
        else if (!locator.IsGeolocationEnabled)
        {
            var page = new Page();
            await page.DisplayAlert("Device Location Service Error!", "Is location on ? Location is off or unavaliable please try again", "Exit");
            throw new ArgumentException("Device location not found, or unavalible,");
        }
    }

    public void OnPropertyChanged(string prop)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
    }
}
1

1 Answers

0
votes

I figured it out.

1.Give your Xaml Object a X:Name="XamlMap"

  1. In the Xaml file Pass the Button object a
    CommandParameter="{x:Reference Name=XamlMap}"

  2. Your Cs File The method that is handling the object, you pass it your object as a parameter like this

    private  void MapTypeChange(Map map)
    {
    
        var xamlMap = map.FindByName<Map>("XamlMap");
        xamlMap.MapType = MapType.Satellite;
    
    }
    

we pass our method a reference to an object of same type.

we use a variable, and use the FindByName passing our generic type, and we

pass our FindByName a string parameter of our Xaml Object name.

then we use the variable to do what ever want want !!!

Happy coding!