From 15e388da7521cc9a59bf625cade6886ab55570bb Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 12 Sep 2019 18:32:07 +0200 Subject: [PATCH] Adding failing binding tests. - `OneTime` bindings are failing to release their subscription if the `DataContext` is unset when the binding is made. - Combining `OneTime` and `OneWayToSource` bindings are causing an NRE. The NRE is being caught but it too results in a subscription being leaked. --- .../Data/BindingTests.cs | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs b/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs index a0a285ee4e..7e053392c7 100644 --- a/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs +++ b/tests/Avalonia.Markup.UnitTests/Data/BindingTests.cs @@ -154,6 +154,18 @@ namespace Avalonia.Markup.UnitTests.Data Assert.Equal("bar", source.Foo); } + [Fact] + public void OneTime_Binding_Releases_Subscription_If_DataContext_Set_Later() + { + var target = new TextBlock(); + var source = new Source { Foo = "foo" }; + + target.Bind(TextBlock.TextProperty, new Binding("Foo", BindingMode.OneTime)); + target.DataContext = source; + + Assert.Equal(0, source.SubscriberCount); + } + [Fact] public void OneWayToSource_Binding_Should_Be_Set_Up() { @@ -567,6 +579,23 @@ namespace Avalonia.Markup.UnitTests.Data Assert.Equal(expected, child.DoubleValue); } + [Fact] + public void Combined_OneTime_And_OneWayToSource_Bindings_Should_Release_Subscriptions() + { + var target1 = new TextBlock(); + var target2 = new TextBlock(); + var root = new Panel { Children = { target1, target2 } }; + var source = new Source { Foo = "foo" }; + + using (target1.Bind(TextBlock.TextProperty, new Binding("Foo", BindingMode.OneTime))) + using (target2.Bind(TextBlock.TextProperty, new Binding("Foo", BindingMode.OneWayToSource))) + { + root.DataContext = source; + } + + Assert.Equal(0, source.SubscriberCount); + } + private class StyledPropertyClass : AvaloniaObject { public static readonly StyledProperty DoubleValueProperty = @@ -646,6 +675,7 @@ namespace Avalonia.Markup.UnitTests.Data public class Source : INotifyPropertyChanged { + private PropertyChangedEventHandler _propertyChanged; private string _foo; public string Foo @@ -661,11 +691,18 @@ namespace Avalonia.Markup.UnitTests.Data public int FooSetCount { get; private set; } - public event PropertyChangedEventHandler PropertyChanged; + + public int SubscriberCount { get; private set; } + + public event PropertyChangedEventHandler PropertyChanged + { + add { _propertyChanged += value; ++SubscriberCount; } + remove { _propertyChanged += value; --SubscriberCount; } + } private void RaisePropertyChanged([CallerMemberName] string prop = "") { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); + _propertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } }