|
|
|
@ -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() |
|
|
|
{ |
|
|
|
@ -196,6 +208,30 @@ namespace Avalonia.Markup.UnitTests.Data |
|
|
|
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] |
|
|
|
public void Default_BindingMode_Should_Be_Used() |
|
|
|
{ |
|
|
|
@ -543,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<double> DoubleValueProperty = |
|
|
|
@ -622,6 +675,7 @@ namespace Avalonia.Markup.UnitTests.Data |
|
|
|
|
|
|
|
public class Source : INotifyPropertyChanged |
|
|
|
{ |
|
|
|
private PropertyChangedEventHandler _propertyChanged; |
|
|
|
private string _foo; |
|
|
|
|
|
|
|
public string Foo |
|
|
|
@ -630,15 +684,25 @@ namespace Avalonia.Markup.UnitTests.Data |
|
|
|
set |
|
|
|
{ |
|
|
|
_foo = value; |
|
|
|
++FooSetCount; |
|
|
|
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 = "") |
|
|
|
{ |
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); |
|
|
|
_propertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|