Home > front end >  Trying to load data from API when Pin is clicked (CustomMap) error: Specified cast is not valid. - x
Trying to load data from API when Pin is clicked (CustomMap) error: Specified cast is not valid. - x

Time:03-28

I'm trying to load the data from API in custom map (xamarin.forms.maps) when user click on pin to send (index 1) on the pin like as parameter.

1. Here I set index 1 on the Address property on the pin:

         List<CustomPin> pins = new List<CustomPin>();

            for (int i = 0; i < HardcodedLocations.Positions.Count; i  )
            {
                CustomPin pin = new CustomPin
                {
                    Type = PinType.Place,
                    Position = HardcodedLocations.Positions[i],
                    Label = "Xamarin San Francisco Office",
                    Address = $"{i   1}",
                    Name = "Xamarin",
                    Url = "http://xamarin.com/about/"
                };

                pins.Add(pin);
                customMap.Pins.Add(pin);
                customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(42.8742, 25.3187), Distance.FromKilometers(250.0)));

            }

            customMap.CustomPins = pins;

2. In CustomMKAnnotationView class I create property Address:

public class CustomMKAnnotationView : MKAnnotationView
{
    public string Name { get; set; }

    public string Url { get; set; }

    public string Address { get; set; }

    public CustomMKAnnotationView(IMKAnnotation annotation, string id)
        : base(annotation, id)
    {
    }

3. In GetViewForAnnotation method in CustomMapRenderer class I appropriate annotationView.Address to be equal on customPin.Address

protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
    {
        MKAnnotationView annotationView = null;

        if (annotation is MKUserLocation)
            return null;

        var customPin = GetCustomPin(annotation as MKPointAnnotation);
        if (customPin == null)
        {
            throw new Exception("Custom pin not found");
        }

        annotationView = mapView.DequeueReusableAnnotation(customPin.Name);
        if (annotationView == null)
        {
            annotationView = new CustomMKAnnotationView(annotation, customPin.Name);
            annotationView.Image = UIImage.FromFile("pin.png");
            annotationView.CalloutOffset = new CGPoint(0, 0);
            annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
            annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
            ((CustomMKAnnotationView)annotationView).Name = customPin.Name;
            ((CustomMKAnnotationView)annotationView).Url = customPin.Url;
            ((CustomMKAnnotationView)annotationView).Address = customPin.Address;
        }
        annotationView.CanShowCallout = true;

        return annotationView;
    }

4. I create a method to get the data from API in CustomMapRenderer class:

string GenerateRequestUri(string endpoint, string date, string id)
    {
        string requestUri = endpoint;
        requestUri  = $"?date={date}";
        requestUri  = $"&id={id}";
        requestUri  = $"&daysForward=8";

        return requestUri;
    }

    public async Task<IEnumerable<AladinModel>> GetDataFromAPI(string indexOnClick)
    {
        DateTime dtNow = DateTime.Now;
        var dtNowAPI = dtNow.ToString("yyyy-MM-dd");

        var listData = new List<AladinModel>();

        var result = await _restServiceAPI.GetAladinData(GenerateRequestUri(ConstantsAPI.EndPoint, dtNowAPI, indexOnClick));

        foreach (var item in result)
        {
            var currentData = new AladinModel()
            {
                
                Dats = item.Dats,
                Ta = item.Ta,
                Rh = item.Rh,
                Ws = item.Ws,
                Rr = item.Rr,
                Sr = item.Sr,
                Apres = item.Apres

        };
            listData.Add(currentData);
        }

        return listData;
    }

5. In OnDidSelectAnnotationView method I trying to send the data with MessagingCenter:

void OnDidSelectAnnotationView(object sender, MKAnnotationViewEventArgs e)
    {
        CustomMKAnnotationView customView = e.View as CustomMKAnnotationView;
        customPinView = new UIView();

        if (customView.Name.Equals("Xamarin"))
        {
            customPinView.Frame = new CGRect(0, 0, 200, 84);
            var image = new UIImageView(new CGRect(0, 0, 200, 84));
            image.Image = UIImage.FromFile("xamarin.png");
            customPinView.AddSubview(image);
            customPinView.Center = new CGPoint(0, -(e.View.Frame.Height   75));
            e.View.AddSubview(customPinView);
        }

        string addressIndex = customView.Address;

        var result = GetDataFromAPI(addressIndex);

        MessagingCenter.Send<object, IEnumerable<AladinModel>>(this, "PinSelected", (IEnumerable<AladinModel>)result);
    }

6. In MainPage I trying to receive the data like that:

        protected override void OnAppearing()
        {
            base.OnAppearing();

            MarkerPressed();

        }

        public void MarkerPressed()
        {
            MessagingCenter.Subscribe<object, IEnumerable<AladinModel>>(this, "PinSelected", (sender, arg) =>
            {
                var test = arg;
            });
        }

When I click on the marker I receive error: Specified cast is not valid on this line:

MessagingCenter.Send<object, IEnumerable<AladinModel>>(this, "PinSelected", (IEnumerable<AladinModel>)result);

Тhis is my object class:

    using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace pizhevsoft.Models
{
    public class ItemsAPI
    {
        public partial class RootAladinModel
        {
            [JsonProperty("aladinModel")]
            public AladinModel[] AladinModel { get; set; }
        }

        public partial class AladinModel
        {
            [JsonProperty("DATS")]
            public DateTime Dats { get; set; }

            [JsonProperty("TA")]
            public double Ta { get; set; }

            [JsonProperty("RH")]
            public double Rh { get; set; }

            [JsonProperty("WS")]
            public double Ws { get; set; }

            [JsonProperty("RR")]
            public double Rr { get; set; }

            [JsonProperty("SR")]
            public double Sr { get; set; }

            [JsonProperty("APRES")]
            public double Apres { get; set; }
        }
    }
}

The main goal when clicking on the marker is to take its index 1, to pass it as a parameter to API to get the data ?

If there is an easier option or way to deal with the problem please share how to do it?

According to my logic, a method GetDataFromAPI must be created in the CustomMapRenderer class, to be called in OnDidSelectAnnotationView, and data to be sending to the Main project with messaging center ?

CodePudding user response:

GetDataFromAPI is an async method and needs to be called using await

  • Related