Browse Source

Merge branch 'master' into fixes/1029-fix-tooltip-crash

pull/1031/head
Steven Kirk 9 years ago
committed by GitHub
parent
commit
a75dfb63a1
  1. 36
      src/Avalonia.Base/Data/BindingNotification.cs
  2. 71
      tests/Avalonia.Markup.UnitTests/Data/BindingExpressionTests.cs
  3. 9
      tests/Avalonia.UnitTests/InvariantCultureFixture.cs

36
src/Avalonia.Base/Data/BindingNotification.cs

@ -44,11 +44,7 @@ namespace Avalonia.Data
public static readonly BindingNotification UnsetValue =
new BindingNotification(AvaloniaProperty.UnsetValue);
// Null cannot be held in WeakReference as it's indistinguishable from an expired value so
// use this value in its place.
private static readonly object NullValue = new object();
private WeakReference<object> _value;
private object _value;
/// <summary>
/// Initializes a new instance of the <see cref="BindingNotification"/> class.
@ -56,7 +52,7 @@ namespace Avalonia.Data
/// <param name="value">The binding value.</param>
public BindingNotification(object value)
{
_value = new WeakReference<object>(value ?? NullValue);
_value = value;
}
/// <summary>
@ -73,6 +69,7 @@ namespace Avalonia.Data
Error = error;
ErrorType = errorType;
_value = AvaloniaProperty.UnsetValue;
}
/// <summary>
@ -84,7 +81,7 @@ namespace Avalonia.Data
public BindingNotification(Exception error, BindingErrorType errorType, object fallbackValue)
: this(error, errorType)
{
_value = new WeakReference<object>(fallbackValue ?? NullValue);
_value = fallbackValue;
}
/// <summary>
@ -95,31 +92,12 @@ namespace Avalonia.Data
/// If this property is read when <see cref="HasValue"/> is false then it will return
/// <see cref="AvaloniaProperty.UnsetValue"/>.
/// </remarks>
public object Value
{
get
{
if (_value != null)
{
object result;
if (_value.TryGetTarget(out result))
{
return result == NullValue ? null : result;
}
}
// There's the possibility of a race condition in that HasValue can return true,
// and then the value is GC'd before Value is read. We should be ok though as
// we return UnsetValue which should be a safe alternative.
return AvaloniaProperty.UnsetValue;
}
}
public object Value => _value;
/// <summary>
/// Gets a value indicating whether <see cref="Value"/> should be pushed to the target.
/// </summary>
public bool HasValue => _value != null;
public bool HasValue => _value != AvaloniaProperty.UnsetValue;
/// <summary>
/// Gets the error that occurred on the source, if any.
@ -256,7 +234,7 @@ namespace Avalonia.Data
/// </summary>
public void SetValue(object value)
{
_value = new WeakReference<object>(value ?? NullValue);
_value = value;
}
/// <inheritdoc/>

71
tests/Avalonia.Markup.UnitTests/Data/BindingExpressionTests.cs

@ -51,11 +51,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public async void Should_Convert_Get_String_To_Double()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { StringValue = "5.6" };
var target = new BindingExpression(new ExpressionObserver(data, "StringValue"), typeof(double));
var result = await target.Take(1);
@ -86,12 +81,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public void Should_Convert_Set_String_To_Double()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { StringValue = (5.6).ToString() };
var target = new BindingExpression(new ExpressionObserver(data, "StringValue"), typeof(double));
@ -103,12 +92,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public async void Should_Convert_Get_Double_To_String()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { DoubleValue = 5.6 };
var target = new BindingExpression(new ExpressionObserver(data, "DoubleValue"), typeof(string));
var result = await target.Take(1);
@ -119,12 +102,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public void Should_Convert_Set_Double_To_String()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { DoubleValue = 5.6 };
var target = new BindingExpression(new ExpressionObserver(data, "DoubleValue"), typeof(string));
@ -136,12 +113,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public async void Should_Return_BindingNotification_With_FallbackValue_For_NonConvertibe_Target_Value()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { StringValue = "foo" };
var target = new BindingExpression(
new ExpressionObserver(data, "StringValue"),
@ -161,12 +132,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact]
public async void Should_Return_BindingNotification_With_FallbackValue_For_NonConvertibe_Target_Value_With_Data_Validation()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { StringValue = "foo" };
var target = new BindingExpression(
new ExpressionObserver(data, "StringValue", true),
@ -186,12 +151,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact(Skip="Result is not always AggregateException.")]
public async void Should_Return_BindingNotification_For_Invalid_FallbackValue()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { StringValue = "foo" };
var target = new BindingExpression(
new ExpressionObserver(data, "StringValue"),
@ -212,12 +171,6 @@ namespace Avalonia.Markup.UnitTests.Data
[Fact(Skip="Result is not always AggregateException.")]
public async void Should_Return_BindingNotification_For_Invalid_FallbackValue_With_Data_Validation()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { StringValue = "foo" };
var target = new BindingExpression(
new ExpressionObserver(data, "StringValue", true),
@ -283,15 +236,9 @@ namespace Avalonia.Markup.UnitTests.Data
Assert.Equal(0, data.DoubleValue);
}
[Fact]
[Fact(Skip="Moq.MockException")]
public void Should_Pass_ConverterParameter_To_Convert()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { DoubleValue = 5.6 };
var converter = new Mock<IValueConverter>();
var target = new BindingExpression(
@ -305,15 +252,9 @@ namespace Avalonia.Markup.UnitTests.Data
converter.Verify(x => x.Convert(5.6, typeof(string), "foo", CultureInfo.InvariantCulture));
}
[Fact]
[Fact(Skip="Moq.MockException")]
public void Should_Pass_ConverterParameter_To_ConvertBack()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { DoubleValue = 5.6 };
var converter = new Mock<IValueConverter>();
var target = new BindingExpression(
@ -327,15 +268,9 @@ namespace Avalonia.Markup.UnitTests.Data
converter.Verify(x => x.ConvertBack("bar", typeof(double), "foo", CultureInfo.InvariantCulture));
}
[Fact]
[Fact(Skip="Moq.MockException")]
public void Should_Handle_DataValidation()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
#else
CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
#endif
var data = new Class1 { DoubleValue = 5.6 };
var converter = new Mock<IValueConverter>();
var target = new BindingExpression(new ExpressionObserver(data, "DoubleValue", true), typeof(string));

9
tests/Avalonia.UnitTests/InvariantCultureFixture.cs

@ -20,13 +20,22 @@ namespace Avalonia.UnitTests
public InvariantCultureFixture()
{
#if NET461
_restore = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
#else
_restore = CultureInfo.CurrentUICulture;
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
#endif
}
public void Dispose()
{
#if NET461
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = _restore;
#else
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = _restore;
#endif
}
}
}

Loading…
Cancel
Save