Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

Confused About MapRenderer OnElementChanged() Event Handler

$
0
0

Greetings all,
I have an app I'm building for work that will render Polygon layers for farm fields on a Google Map in both Android and iOS. I used the official tutorial for highlighting a region which everyone is familiar with (I can't link it.)

After a bit of tweaking I am able to get a polygon layer to load and bring into view successfully. Any time I attempt to update the map to a new region no new polygons will load. I notice that the first time I load the polygon to the map both the ElementChanged and ElementPropertyChanged events fire and are handled in my Android CustomMapRenderer. But when I attempt to update the map by triggering a property binding change only the ElementPropertyChanged event fires. What I'm trying to understand is what exactly causes the ElementChanged event to fire. I can't seem to find this info anywhere. There is code I put in that event handler that is crucial to looking up the new data about where the new polygons need to be rendered. Here's what my overrides look like within the CustomMapRenderer:

        protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                // Unsubscribe
            }

            if (e.NewElement == null) return;

    // Because this block below never gets called after the first time the Polygon data
    // does not update and hence the UpdateMapContours method in the handler below 
    // just rerenders the same polygon it initially loaded.

            var formsMap = (CustomMap) e.NewElement;
            _multiPolygon = formsMap.MapPolygonData;
            Control.GetMapAsync(this);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
    // I have no access to the CustomMap element here as I do in the above override
    // so I cannot locate the new MapPolygonData necessary.

            base.OnElementPropertyChanged(sender, e);
            if (Element == null || Control == null)
                return;

            if (e.PropertyName == CustomMap.MapPolygonDataProperty.PropertyName)
            {
                UpdateMapContours();
            }
        }

The rest of the picture looks like this. In my CustomMap class I have a custom BindableProperty so I can update in the ViewModel and trigger the map to load a new polygon and bring to view. It's like this:

    public class CustomMap : Map
    {
        public static readonly BindableProperty MapPolygonDataProperty = BindableProperty.Create(
            nameof(MapPolygonData),
            typeof(MultiPolygon),
            typeof(CustomMap),
            propertyChanged: (b, o, n) =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
            ...
            // Omitted logic for calculating map region to display
            ...
                    ((CustomMap) b).MoveToRegion(MapSpan.FromCenterAndRadius(geometryCenter, Distance.FromMeters(displayRadiusMeters)));
                });
            });

        public MultiPolygon MapPolygonData
        {
            get { return (MultiPolygon)GetValue(MapPolygonDataProperty); }
            set { SetValue(MapPolygonDataProperty, value); }
        }

        public CustomMap ()
        {
            MapPolygonData = new MultiPolygon();
        }
    }

In my ViewModel I am setting the BindableProperty with new polygondata (triggering the ElementPropertyChanged event) which then triggers the delegate function in CustomMap which tells the map where to move its focus. Again, when I set the MapPolygonData property in the constructor everything works fine but when it is set in the LoadContour method only the ElementPropertyChanged event fires.

    public class MapViewModel : ViewModelBase
    {
        private MultiPolygon _mapPolygonData;
        private readonly IContourService _contourService;

        public ICommand TestContourCommand => new Command(() => LoadContour());

        public MultiPolygon MapPolygonData
        {
            get { return _mapPolygonData; }
            set
            {
                _mapPolygonData = value;
                RaisePropertyChanged(() => MapPolygonData);
            }
        }

        public MapViewModel(IContourService contourService)
        {
            _contourService = contourService;
            var contours = _contourService.GetContoursAsync();
            MapPolygonData = _contourService.ConvertContourDataToMultipolygon(contours);
        }

        private void LoadContour()
        {
            var contours = _contourService.GetContoursAsync(testContour);
            MapPolygonData = _contourService.ConvertContourDataToMultipolygon(contours);
        }
    }

Any help is appreciated. If anyone sees a better way for me to accomplish or additional problems this I'd be happy to hear.
Thanks


Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>