summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core/Interactivity/AttachedCollection.cs')
-rw-r--r--Xamarin.Forms.Core/Interactivity/AttachedCollection.cs127
1 files changed, 127 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs b/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs
new file mode 100644
index 00000000..6aff5147
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/AttachedCollection.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Xamarin.Forms
+{
+ internal class AttachedCollection<T> : ObservableCollection<T>, ICollection<T>, IAttachedObject where T : BindableObject, IAttachedObject
+ {
+ readonly List<WeakReference> _associatedObjects = new List<WeakReference>();
+
+ public AttachedCollection()
+ {
+ }
+
+ public AttachedCollection(IEnumerable<T> collection) : base(collection)
+ {
+ }
+
+ public AttachedCollection(IList<T> list) : base(list)
+ {
+ }
+
+ public void AttachTo(BindableObject bindable)
+ {
+ if (bindable == null)
+ throw new ArgumentNullException("bindable");
+ OnAttachedTo(bindable);
+ }
+
+ public void DetachFrom(BindableObject bindable)
+ {
+ OnDetachingFrom(bindable);
+ }
+
+ protected override void ClearItems()
+ {
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ foreach (T item in this)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.DetachFrom(bindable);
+ }
+ }
+ base.ClearItems();
+ }
+
+ protected override void InsertItem(int index, T item)
+ {
+ base.InsertItem(index, item);
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.AttachTo(bindable);
+ }
+ }
+
+ protected virtual void OnAttachedTo(BindableObject bindable)
+ {
+ lock(_associatedObjects)
+ {
+ _associatedObjects.Add(new WeakReference(bindable));
+ }
+ foreach (T item in this)
+ item.AttachTo(bindable);
+ }
+
+ protected virtual void OnDetachingFrom(BindableObject bindable)
+ {
+ foreach (T item in this)
+ item.DetachFrom(bindable);
+ lock(_associatedObjects)
+ {
+ for (var i = 0; i < _associatedObjects.Count; i++)
+ {
+ object target = _associatedObjects[i].Target;
+
+ if (target == null || target == bindable)
+ {
+ _associatedObjects.RemoveAt(i);
+ i--;
+ }
+ }
+ }
+ }
+
+ protected override void RemoveItem(int index)
+ {
+ T item = this[index];
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.DetachFrom(bindable);
+ }
+
+ base.RemoveItem(index);
+ }
+
+ protected override void SetItem(int index, T item)
+ {
+ T old = this[index];
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ old.DetachFrom(bindable);
+ }
+
+ base.SetItem(index, item);
+
+ foreach (WeakReference weakbindable in _associatedObjects)
+ {
+ var bindable = weakbindable.Target as BindableObject;
+ if (bindable == null)
+ continue;
+ item.AttachTo(bindable);
+ }
+ }
+ }
+} \ No newline at end of file