2021年1月17日星期日

How to fix .Exception: 'Custom pin not found for specific pins

Please help me with this issue. I was making a custom renderer in xamarin using this article: Xamarin Form Custom Renderer

Everything worked fine until I made the pin information into a JSON file.

So basically now the LAT, LNG, label, name and URL were stored in a JSON file instead of a C# file. For testing, I had made 3 temporary pins. But only 1 of them shows the custom rendered window. When I click the other 2 pins an exception occurs as custom pin not found. But the custom pin is found for the last pin but not the 1st and 2nd pin which confuses me.

My code:

JSON file:

[    {"Label"   :"Country1",          "Address":"A multine paragraph",          "Lat":"-12",          "Lng":"14",          "Name":"Xamarin",           "Url": "http://xamarin.com/about/"  },      { "Label"  :"Country2",           "Address":"Multiline paragraph",           "Lat":"-25",            "Lng":"45",           "Name":"Xamarin",           "Url": "http://xamarin.com/about/"  },    { "Label"  :"Country3",           "Address":"Multiline paragraph",           "Lat":"-5",            "Lng":"45",           "Name":"Xamarin",           "Url": "http://xamarin.com/about/"  }    ]  

CustomPin.cs:

using System;  using System.Collections.Generic;  using System.Text;  using Xamarin.Forms.Maps;    namespace ------  {      public class CustomPin : Pin      {          public string Name { get; set; }          public string Url { get; set; }      }  }  

MapPage.xaml.cs:

using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Threading.Tasks;  using Xamarin.Forms;  using Xamarin.Forms.Maps;  using Newtonsoft.Json;  using System.IO;  using Xamarin.Forms.Xaml;  using System.Reflection;        namespace ----  {      public partial class MapPage : ContentPage      {          public MapPage()          {              CustomMap customMap = new CustomMap              {                  MapType = MapType.Hybrid              };                Content = customMap;                var assembly = IntrospectionExtensions.GetTypeInfo(typeof(MapPage)).Assembly;              Stream stream = assembly.GetManifestResourceStream("Orbage.Mydata.json");              string json = "";              using (var reader = new System.IO.StreamReader(stream))              {                  json = reader.ReadToEnd();              }              var places = JsonConvert.DeserializeObject<List<Mydata>>(json);              foreach (var place in places)              {                  CustomPin pin = new CustomPin                  {                      Type = PinType.Place,                      Position = new Position(Double.Parse(place.Lat), Double.Parse(place.Lng)),                      Label = place.Label,                      Address = place.Address,                      Name = place.Name,                      Url = place.Url                  };                  customMap.CustomPins = new List<CustomPin> { pin };                  customMap.Pins.Add(pin);                  customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Distance.FromMiles(1.0)));              }          }      }      public class Mydata      {          public string Label { get; set; }          public string Address { get; set; }          public string Lat { get; set; }          public string Lng { get; set; }          public string Name { get; set; }          public string Url { get; set; }      }  }  

CustomMapRenderer.cs:

using System;  using System.Collections.Generic;  using Android.Content;  using Android.Gms.Maps;  using Android.Gms.Maps.Model;  using Android.Widget;  using ----;  using ----.Droid;  using Xamarin.Forms;  using Xamarin.Forms.Maps;  using Xamarin.Forms.Maps.Android;    [assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]  namespace ----.Droid  {      public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter      {          List<CustomPin> customPins;            public CustomMapRenderer(Context context) : base(context)          {          }            protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)          {              base.OnElementChanged(e);                if (e.OldElement != null)              {                  NativeMap.InfoWindowClick -= OnInfoWindowClick;              }                if (e.NewElement != null)              {                  var formsMap = (CustomMap)e.NewElement;                  customPins = formsMap.CustomPins;              }          }            protected override void OnMapReady(GoogleMap map)          {              base.OnMapReady(map);                NativeMap.InfoWindowClick += OnInfoWindowClick;              NativeMap.SetInfoWindowAdapter(this);          }            protected override MarkerOptions CreateMarker(Pin pin)          {              var marker = new MarkerOptions();              marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));              marker.SetTitle(pin.Label);              marker.SetSnippet(pin.Address);              marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));              return marker;          }            void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)          {              var customPin = GetCustomPin(e.Marker);              if (customPin == null)              {                  throw new Exception("Custom pin not found");              }                if (!string.IsNullOrWhiteSpace(customPin.Url))              {                  var url = Android.Net.Uri.Parse(customPin.Url);                  var intent = new Intent(Intent.ActionView, url);                  intent.AddFlags(ActivityFlags.NewTask);                  Android.App.Application.Context.StartActivity(intent);              }          }            public Android.Views.View GetInfoContents(Marker marker)          {              var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater;              if (inflater != null)              {                  Android.Views.View view;                    var customPin = GetCustomPin(marker);                  if (customPin == null)                  {                      throw new Exception("Custom pin not found");                  }                    if (customPin.Name.Equals("Xamarin"))                  {                      view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);                  }                  else                  {                      view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);                  }                    var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);                  var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);                    if (infoTitle != null)                  {                      infoTitle.Text = marker.Title;                  }                  if (infoSubtitle != null)                  {                      infoSubtitle.Text = marker.Snippet;                  }                    return view;              }              return null;          }            public Android.Views.View GetInfoWindow(Marker marker)          {              return null;          }            CustomPin GetCustomPin(Marker annotation)          {              var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);              foreach (var pin in customPins)              {                  if (pin.Position == position)                  {                      return pin;                  }              }              return null;          }      }  }  

Thanks for seeing this and I hope this get's answered and someone with the same error gets it fixed. :)

I tried debugging and here is a image of what somewhat might help: enter image description here

https://stackoverflow.com/questions/65763631/how-to-fix-exception-custom-pin-not-found-for-specific-pins January 18, 2021 at 01:15AM

没有评论:

发表评论