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