-
-
Save vackup/d661317f9f04d0a93e5f048a820c0760 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// an abstract helper class | |
public abstract class MvxAnnotationManager | |
{ | |
private readonly MKMapView _mapView; | |
private IEnumerable _itemsSource; | |
private IDisposable _subscription; | |
public Dictionary<object, MKAnnotation> _annotations = new Dictionary<object, MKAnnotation>(); | |
protected MvxAnnotationManager(MKMapView mapView) | |
{ | |
_mapView = mapView; | |
} | |
// MvxSetToNullAfterBinding isn't strictly needed any more | |
// - but it's nice to have for when binding is torn down | |
[MvxSetToNullAfterBinding] | |
public virtual IEnumerable ItemsSource | |
{ | |
get { return _itemsSource; } | |
set { SetItemsSource(value); } | |
} | |
protected virtual void SetItemsSource(IEnumerable value) | |
{ | |
if (_itemsSource == value) | |
return; | |
if (_subscription != null) | |
{ | |
_subscription.Dispose(); | |
_subscription = null; | |
} | |
_itemsSource = value; | |
if (_itemsSource != null && !(_itemsSource is IList)) | |
MvxBindingTrace.Trace(MvxTraceLevel.Warning, | |
"Binding to IEnumerable rather than IList - this can be inefficient, especially for large lists"); | |
ReloadAllAnnotations(); | |
var newObservable = _itemsSource as INotifyCollectionChanged; | |
if (newObservable != null) | |
{ | |
_subscription = newObservable.WeakSubscribe(OnItemsSourceCollectionChanged); | |
} | |
} | |
protected virtual void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) | |
{ | |
switch (e.Action) | |
{ | |
case NotifyCollectionChangedAction.Add: | |
AddAnnotations(e.NewItems); | |
break; | |
case NotifyCollectionChangedAction.Remove: | |
RemoveAnnotations(e.OldItems); | |
break; | |
case NotifyCollectionChangedAction.Replace: | |
RemoveAnnotations(e.OldItems); | |
AddAnnotations(e.NewItems); | |
break; | |
case NotifyCollectionChangedAction.Move: | |
// not interested in this | |
break; | |
case NotifyCollectionChangedAction.Reset: | |
ReloadAllAnnotations(); | |
break; | |
default: | |
throw new ArgumentOutOfRangeException(); | |
} | |
} | |
protected virtual void ReloadAllAnnotations() | |
{ | |
_mapView.RemoveAnnotations(_annotations.Values.Select(x => (NSObject)x).ToArray()); | |
_annotations.Clear(); | |
if (_itemsSource == null) | |
return; | |
AddAnnotations(_itemsSource); | |
} | |
protected abstract MKAnnotation CreateAnnotation(object item); | |
protected virtual void RemoveAnnotations(IEnumerable oldItems) | |
{ | |
foreach (var item in oldItems) | |
{ | |
RemoveAnnotationFor(item); | |
} | |
} | |
protected virtual void RemoveAnnotationFor(object item) | |
{ | |
var annotation = _annotations[item]; | |
_mapView.RemoveAnnotation(annotation); | |
_annotations.Remove(item); | |
} | |
protected virtual void AddAnnotations(IEnumerable newItems) | |
{ | |
foreach (object item in newItems) | |
{ | |
AddAnnotationFor(item); | |
} | |
} | |
protected virtual void AddAnnotationFor(object item) | |
{ | |
var annotation = CreateAnnotation(item); | |
_annotations[item] = annotation; | |
_mapView.AddAnnotation(annotation); | |
} | |
} | |
// example use | |
public class House | |
{ | |
public double Lat { get; set; } | |
public double Lng { get; set; } | |
public string Name { get; set; } | |
} | |
public class FirstViewModel : MvxViewModel | |
{ | |
public ObservableCollection<House> Houses { get; set; } | |
} | |
public class HouseAnnotationManager | |
: MvxAnnotationManager | |
{ | |
public HouseAnnotationManager(MKMapView mapView) : base(mapView) | |
{ | |
} | |
protected override MKAnnotation CreateAnnotation(object item) | |
{ | |
var house = item as House; | |
return new HouseAnnotation(item); | |
} | |
} | |
public class HouseAnnotation : MKAnnotation | |
{ | |
public HouseAnnotation(House house) | |
{ | |
// use house here... | |
// in theory you could also data-bind to the house too (e.g. if it's location were to move...) | |
} | |
public override CLLocationCoordinate2D Coordinate { get; set; } | |
} | |
[Register("FirstView")] | |
public class FirstView : MvxViewController | |
{ | |
private HouseAnnotationManager _manager; | |
public override void ViewDidLoad() | |
{ | |
View = new UIView(){ BackgroundColor = UIColor.White}; | |
base.ViewDidLoad(); | |
var myMapView = new MKMapView(View.Frame); | |
Add(myMapView); | |
myMapView.Delegate = new MyMapDelegate(); // standard map delegate - must provide the annotation views | |
_manager = new HouseAnnotationManager(myMapView); | |
var set = this.CreateBindingSet<FirstView, FirstViewModel>(); | |
set.Bind(_manager).For(m => m.ItemsSource).To(vm => vm.HouseList); | |
set.Apply(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment