summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xamarin.Forms.Core.UnitTests/BehaviorTest.cs42
-rw-r--r--Xamarin.Forms.Core/BindableObject.cs8
-rw-r--r--Xamarin.Forms.Core/VisualElement.cs13
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml16
4 files changed, 78 insertions, 1 deletions
diff --git a/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs b/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs
index 78e0cfb0..90217389 100644
--- a/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs
+++ b/Xamarin.Forms.Core.UnitTests/BehaviorTest.cs
@@ -3,8 +3,9 @@ using NUnit.Framework;
namespace Xamarin.Forms.Core.UnitTests
{
- internal class MockBehavior<T> : Behavior<T> where T:BindableObject
+ class MockBehavior<T> : Behavior<T> where T:BindableObject
{
+ public static int AttachCount { get; set; }
public bool attached;
public bool detached;
@@ -12,11 +13,13 @@ namespace Xamarin.Forms.Core.UnitTests
{
base.OnAttachedTo (bindable);
attached = true;
+ AttachCount++;
AssociatedObject = bindable;
}
protected override void OnDetachingFrom (BindableObject bindable)
{
+ AttachCount--;
detached = true;
base.OnDetachingFrom (bindable);
AssociatedObject = null;
@@ -106,5 +109,42 @@ namespace Xamarin.Forms.Core.UnitTests
collection.Remove (behavior);
Assert.Null (behavior.AssociatedObject);
}
+
+ [Test]
+ //https://bugzilla.xamarin.com/show_bug.cgi?id=44074
+ public void TestBehaviorsAreDetachedBeforeGarbageCollection()
+ {
+ WeakReference weakBindable = null;
+
+ var attachCount = MockBehavior<VisualElement>.AttachCount;
+
+ int i = 0;
+ Action create = null;
+ create = () =>
+ {
+ if (i++ < 1024)
+ {
+ create();
+ return;
+ }
+
+ var bindable = new MockBindable
+ {
+ Behaviors = {
+ new MockBehavior<VisualElement> ()
+ }
+ };
+ weakBindable = new WeakReference(bindable);
+ };
+
+ create();
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+
+ Assert.False(weakBindable.IsAlive);
+ Assert.AreEqual(attachCount, MockBehavior<VisualElement>.AttachCount);
+ }
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/BindableObject.cs b/Xamarin.Forms.Core/BindableObject.cs
index 217f4a94..b5e41452 100644
--- a/Xamarin.Forms.Core/BindableObject.cs
+++ b/Xamarin.Forms.Core/BindableObject.cs
@@ -163,6 +163,14 @@ namespace Xamarin.Forms
return bpcontext != null && bpcontext.Binding != null;
}
+ internal bool GetIsDefault(BindableProperty targetProperty)
+ {
+ if (targetProperty == null)
+ throw new ArgumentNullException(nameof(targetProperty));
+
+ return GetContext(targetProperty) == null;
+ }
+
internal object[] GetValues(BindableProperty property0, BindableProperty property1)
{
var values = new object[2];
diff --git a/Xamarin.Forms.Core/VisualElement.cs b/Xamarin.Forms.Core/VisualElement.cs
index 053ddb0a..cff1eb10 100644
--- a/Xamarin.Forms.Core/VisualElement.cs
+++ b/Xamarin.Forms.Core/VisualElement.cs
@@ -781,5 +781,18 @@ namespace Xamarin.Forms
public bool Result { get; set; }
}
+
+ ~VisualElement()
+ {
+ if (!GetIsDefault(BehaviorsProperty)) {
+ var behaviors = GetValue(BehaviorsProperty) as AttachedCollection<Behavior>;
+ behaviors.DetachFrom(this);
+ }
+
+ if (!GetIsDefault(TriggersProperty)) {
+ var triggers = GetValue(TriggersProperty) as AttachedCollection<Trigger>;
+ triggers.DetachFrom(this);
+ }
+ }
}
} \ No newline at end of file
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml
index 426d8c60..9b28bf08 100644
--- a/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml
@@ -290,6 +290,22 @@
</remarks>
</Docs>
</Member>
+ <Member MemberName="Finalize">
+ <MemberSignature Language="C#" Value="~VisualElement ();" />
+ <MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void Finalize() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Void</ReturnType>
+ </ReturnValue>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
<Member MemberName="Focus">
<MemberSignature Language="C#" Value="public bool Focus ();" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig instance bool Focus() cil managed" />