Browse Source

Merge branch 'master' into fixes/3552-dash-class-name

pull/4213/head
Benedikt Stebner 6 years ago
committed by GitHub
parent
commit
b4ed5004d0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      src/Avalonia.Base/Data/Core/LogicalNotNode.cs
  2. 78
      tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_Negation.cs

36
src/Avalonia.Base/Data/Core/LogicalNotNode.cs

@ -12,8 +12,19 @@ namespace Avalonia.Data.Core
base.NextValueChanged(Negate(value));
}
private static object Negate(object v)
private static object Negate(object value)
{
var notification = value as BindingNotification;
var v = BindingNotification.ExtractValue(value);
BindingNotification GenerateError(Exception e)
{
notification ??= new BindingNotification(AvaloniaProperty.UnsetValue);
notification.AddError(e, BindingErrorType.Error);
notification.ClearValue();
return notification;
}
if (v != AvaloniaProperty.UnsetValue)
{
var s = v as string;
@ -28,9 +39,7 @@ namespace Avalonia.Data.Core
}
else
{
return new BindingNotification(
new InvalidCastException($"Unable to convert '{s}' to bool."),
BindingErrorType.Error);
return GenerateError(new InvalidCastException($"Unable to convert '{s}' to bool."));
}
}
else
@ -38,24 +47,31 @@ namespace Avalonia.Data.Core
try
{
var boolean = Convert.ToBoolean(v, CultureInfo.InvariantCulture);
return !boolean;
if (notification is object)
{
notification.SetValue(!boolean);
return notification;
}
else
{
return !boolean;
}
}
catch (InvalidCastException)
{
// The error message here is "Unable to cast object of type 'System.Object'
// to type 'System.IConvertible'" which is kinda useless so provide our own.
return new BindingNotification(
new InvalidCastException($"Unable to convert '{v}' to bool."),
BindingErrorType.Error);
return GenerateError(new InvalidCastException($"Unable to convert '{v}' to bool."));
}
catch (Exception e)
{
return new BindingNotification(e, BindingErrorType.Error);
return GenerateError(e);
}
}
}
return AvaloniaProperty.UnsetValue;
return notification ?? AvaloniaProperty.UnsetValue;
}
public object Transform(object value)

78
tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_Negation.cs

@ -1,4 +1,6 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Avalonia.Data;
@ -89,6 +91,69 @@ namespace Avalonia.Markup.UnitTests.Parsers
GC.KeepAlive(data);
}
[Fact]
public async Task Should_Negate_BindingNotification_Value()
{
var data = new { Foo = true };
var target = ExpressionObserverBuilder.Build(data, "!Foo", enableDataValidation: true);
var result = await target.Take(1);
Assert.Equal(new BindingNotification(false), result);
GC.KeepAlive(data);
}
[Fact]
public async Task Should_Pass_Through_BindingNotification_Error()
{
var data = new { };
var target = ExpressionObserverBuilder.Build(data, "!Foo", enableDataValidation: true);
var result = await target.Take(1);
Assert.Equal(
new BindingNotification(
new MissingMemberException("Could not find a matching property accessor for 'Foo' on '{ }'"),
BindingErrorType.Error),
result);
GC.KeepAlive(data);
}
[Fact]
public async Task Should_Negate_BindingNotification_Error_FallbackValue()
{
var data = new Test { DataValidationError = "Test error" };
var target = ExpressionObserverBuilder.Build(data, "!Foo", enableDataValidation: true);
var result = await target.Take(1);
Assert.Equal(
new BindingNotification(
new DataValidationException("Test error"),
BindingErrorType.DataValidationError,
true),
result);
GC.KeepAlive(data);
}
[Fact]
public async Task Should_Add_Error_To_BindingNotification_For_FallbackValue_Not_Convertible_To_Boolean()
{
var data = new Test { Bar = new object(), DataValidationError = "Test error" };
var target = ExpressionObserverBuilder.Build(data, "!Bar", enableDataValidation: true);
var result = await target.Take(1);
Assert.Equal(
new BindingNotification(
new AggregateException(
new DataValidationException("Test error"),
new InvalidCastException($"Unable to convert 'System.Object' to bool.")),
BindingErrorType.Error),
result);
GC.KeepAlive(data);
}
[Fact]
public void SetValue_Should_Return_False_For_Invalid_Value()
{
@ -101,9 +166,20 @@ namespace Avalonia.Markup.UnitTests.Parsers
GC.KeepAlive(data);
}
private class Test
private class Test : INotifyDataErrorInfo
{
public bool Foo { get; set; }
public object Bar { get; set; }
public string DataValidationError { get; set; }
public bool HasErrors => !string.IsNullOrWhiteSpace(DataValidationError);
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public IEnumerable GetErrors(string propertyName)
{
return DataValidationError is object ? new[] { DataValidationError } : null;
}
}
}
}

Loading…
Cancel
Save