|
@@ -154,6 +154,18 @@ namespace Avalonia.Markup.UnitTests.Data
|
|
|
Assert.Equal("bar", source.Foo);
|
|
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]
|
|
[Fact]
|
|
|
public void OneWayToSource_Binding_Should_Be_Set_Up()
|
|
public void OneWayToSource_Binding_Should_Be_Set_Up()
|
|
|
{
|
|
{
|
|
@@ -196,6 +208,30 @@ namespace Avalonia.Markup.UnitTests.Data
|
|
|
Assert.Equal("baz", target.Text);
|
|
Assert.Equal("baz", target.Text);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ [Fact]
|
|
|
|
|
+ public void OneWayToSource_Binding_Should_Not_StackOverflow_With_Null_Value()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Issue #2912
|
|
|
|
|
+ var target = new TextBlock { Text = null };
|
|
|
|
|
+ var binding = new Binding
|
|
|
|
|
+ {
|
|
|
|
|
+ Path = "Foo",
|
|
|
|
|
+ Mode = BindingMode.OneWayToSource,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ target.Bind(TextBox.TextProperty, binding);
|
|
|
|
|
+
|
|
|
|
|
+ var source = new Source { Foo = "foo" };
|
|
|
|
|
+ target.DataContext = source;
|
|
|
|
|
+
|
|
|
|
|
+ Assert.Null(source.Foo);
|
|
|
|
|
+
|
|
|
|
|
+ // When running tests under NCrunch, NCrunch replaces the standard StackOverflowException
|
|
|
|
|
+ // with its own, which will be caught by our code. Detect the stackoverflow anyway, by
|
|
|
|
|
+ // making sure the target property was only set once.
|
|
|
|
|
+ Assert.Equal(2, source.FooSetCount);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
[Fact]
|
|
[Fact]
|
|
|
public void Default_BindingMode_Should_Be_Used()
|
|
public void Default_BindingMode_Should_Be_Used()
|
|
|
{
|
|
{
|
|
@@ -543,6 +579,23 @@ namespace Avalonia.Markup.UnitTests.Data
|
|
|
Assert.Equal(expected, child.DoubleValue);
|
|
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
|
|
private class StyledPropertyClass : AvaloniaObject
|
|
|
{
|
|
{
|
|
|
public static readonly StyledProperty<double> DoubleValueProperty =
|
|
public static readonly StyledProperty<double> DoubleValueProperty =
|
|
@@ -622,6 +675,7 @@ namespace Avalonia.Markup.UnitTests.Data
|
|
|
|
|
|
|
|
public class Source : INotifyPropertyChanged
|
|
public class Source : INotifyPropertyChanged
|
|
|
{
|
|
{
|
|
|
|
|
+ private PropertyChangedEventHandler _propertyChanged;
|
|
|
private string _foo;
|
|
private string _foo;
|
|
|
|
|
|
|
|
public string Foo
|
|
public string Foo
|
|
@@ -630,15 +684,25 @@ namespace Avalonia.Markup.UnitTests.Data
|
|
|
set
|
|
set
|
|
|
{
|
|
{
|
|
|
_foo = value;
|
|
_foo = value;
|
|
|
|
|
+ ++FooSetCount;
|
|
|
RaisePropertyChanged();
|
|
RaisePropertyChanged();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
|
|
|
+ public int FooSetCount { get; private set; }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ public int SubscriberCount { get; private set; }
|
|
|
|
|
+
|
|
|
|
|
+ public event PropertyChangedEventHandler PropertyChanged
|
|
|
|
|
+ {
|
|
|
|
|
+ add { _propertyChanged += value; ++SubscriberCount; }
|
|
|
|
|
+ remove { _propertyChanged += value; --SubscriberCount; }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
private void RaisePropertyChanged([CallerMemberName] string prop = "")
|
|
private void RaisePropertyChanged([CallerMemberName] string prop = "")
|
|
|
{
|
|
{
|
|
|
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
|
|
|
|
|
|
|
+ _propertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|