Posted at

Xamarin.Forms.GoogleMapsのPinにReadOnlyObservableCollection<Pin>をバインドする

More than 1 year has passed since last update.

BehaviorBaseはnuitsjpさんのコードから拝借しました。

https://github.com/nuitsjp/Xamarin.Forms.GoogleMaps.Bindings


public sealed class BindingPinsBehavior : BehaviorBase<Map>
{
void HandleNotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
var items = e.NewItems.Cast<Pin>().ToArray();
for (int i = 0; i < items.Length; i++)
{
_pins.Insert(e.NewStartingIndex + i, items[i]);
}
break;
case NotifyCollectionChangedAction.Remove:
var oldItems = e.OldItems.Cast<Pin>().ToArray();
foreach (var item in oldItems)
{
_pins.Remove(item);
}
break;
case NotifyCollectionChangedAction.Reset:
_pins.Clear();
break;
default:
break;
}
}

public static readonly BindableProperty ValueProperty = BindableProperty.Create("Value", typeof(ReadOnlyObservableCollection<Pin>), typeof(BindingPinsBehavior), default(ReadOnlyObservableCollection<Pin>)
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, oldValue, newValue) =>
{
var b = bindable as BindingPinsBehavior;
if (oldValue != null)
{
(oldValue as INotifyCollectionChanged).CollectionChanged -= b.HandleNotifyCollectionChangedEventHandler;
}
if (newValue != null)
{
(newValue as INotifyCollectionChanged).CollectionChanged += b.HandleNotifyCollectionChangedEventHandler;
}
});
public ReadOnlyObservableCollection<Pin> Value
{
get => (ReadOnlyObservableCollection<Pin>)GetValue(ValueProperty);
set
{

SetValue(ValueProperty, value);

}
}

private ObservableCollection<Pin> _pins;

protected override void OnAttachedTo(Map bindable)
{
base.OnAttachedTo(bindable);
_pins = bindable.Pins as ObservableCollection<Pin>;
if (Value != null)
{
(Value as INotifyCollectionChanged).CollectionChanged += HandleNotifyCollectionChangedEventHandler;
}
}

protected override void OnDetachingFrom(Map bindable)
{
base.OnDetachingFrom(bindable);
_pins = null;
}
}

public class BehaviorBase<T> : Behavior<T> where T : BindableObject
{
public T AssociatedObject { get; private set; }

internal BehaviorBase()
{
}

protected override void OnAttachedTo(T bindable)
{
base.OnAttachedTo(bindable);
AssociatedObject = bindable;

if (bindable.BindingContext != null)
{
BindingContext = bindable.BindingContext;
}

bindable.BindingContextChanged += OnBindingContextChanged;
}

protected override void OnDetachingFrom(T bindable)
{
base.OnDetachingFrom(bindable);
bindable.BindingContextChanged -= OnBindingContextChanged;
AssociatedObject = null;
}

private void OnBindingContextChanged(object sender, EventArgs e)
{
OnBindingContextChanged();
}

protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
BindingContext = AssociatedObject.BindingContext;
}
}