(Error: Custom pin not found) when trying to fill map with markers from hardcoded locations

115 Views Asked by At

I want to fill the map with hard coded coordinates to display the pin markers with custom map using Xamarin.Forms.Maps

My HardcodeLocations class is:

public class HardcodedLocations
{
    public static List<Position> Positions = new List<Position>
    {
           new Position(41.19197,   25.33719 ),
           new Position(41.26352,   25.1471 ),
           new Position(41.26365,   25.24215 ),
           new Position(41.26369,   25.33719 ),
           new Position(41.26365,   25.43224 ),
     };
}

In the constructor class I trying to load the markers like that:

public AboutPage()
{
    InitializeComponent();

    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 = "394 Pacific Ave, San Francisco CA",
            Name = "Xamarin",
            Url = "http://xamarin.com/about/"
        };
        customMap.CustomPins = new List<CustomPin> { pin };
        customMap.Pins.Add(pin);
        customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(42.8742, 25.3187), Distance.FromMiles(1.0)));
    }
}

but I receive error here in CustomMapRender class in iOS project:

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

This is all code in the GetViewForAnnotation method in the same class:

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;
    }
    annotationView.CanShowCallout = true;

    return annotationView;
}

I don't know how to fix this error because when I use basic xamarin.forms.maps (without customizing) I just fill the map like that:

for (int i = 0; i < HardcodedLocations.Positions.Count; i++)
{
    Pin pin = new Pin
    {
        //Label = $"{i + 1}",
        Label = $"{i + 1}",
        Address = "Кликни тук за да видиш прогнозата.",
        Type = PinType.Place,
        Position = HardcodedLocations.Positions[i]
    };

    map.Pins.Add(pin);
}

This is the method of GetCustomPin:

CustomPin GetCustomPin(MKPointAnnotation annotation)
    {
        var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude);
        foreach (var pin in customPins)
        {
            if (pin.Position == position)
            {
                return pin;
            }
        }
        return null;
    }

This is the CustomPin code:

    public class CustomPin : Pin
{
    public string Name { get; set; }
    public string Url { get; set; }
}

To change the pin, the entire code had to be refactoring with creating CustomMap and CustomPin classes in the basic project and creating CustomMapRenderer and CustomMKAnnotationView classes in iOS and Android project.

Reference: https://github.com/xamarin/xamarin-forms-samples/tree/main/CustomRenderers/Map

Is there a way to clear this error?

=================================== UPDATE

In this method I trying to compare two Position properties like that:

CustomPin GetCustomPin(MKPointAnnotation annotation)
    {

        var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude);

        foreach (var pin in customPins)
        {
            if (pin.Position.Latitude == position.Latitude && pin.Position.Longitude == position.Longitude)
            {
                return pin;
            }
        }
        return null;
    }

But I still receive the same error ;(

1

There are 1 best solutions below

2
On BEST ANSWER

As Jason points out in the comments you need to change how you add items to the map.

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 = "394 Pacific Ave, San Francisco CA",
        Name = "Xamarin",
        Url = "http://xamarin.com/about/"
    };
    
    customMap.Pins.Add(pin);
}

customMap.CustomPins = pins;
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(42.8742, 25.3187), Distance.FromMiles(1.0)));

You were overwriting CustomPins with a new list with a single item every iteration of your loop.