Browse Source

Fix OneTime bindings.

OneTime bindings were failing in BindingTest because the initial binding
error was being counted as the single value to transfer. Don't do this
with OneTime bindings - only transfer valid values.
pull/691/head
Steven Kirk 10 years ago
parent
commit
8b9f25ff24
  1. 15
      src/Avalonia.Base/Data/BindingNotification.cs
  2. 5
      src/Avalonia.Base/Data/BindingOperations.cs
  3. 49
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs

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

@ -166,6 +166,21 @@ namespace Avalonia.Data
return !(a == b);
}
/// <summary>
/// Gets a value from an object that may be a <see cref="BindingNotification"/>.
/// </summary>
/// <param name="o">The object.</param>
/// <returns>The value.</returns>
/// <remarks>
/// If <paramref name="o"/> is a <see cref="BindingNotification"/> then returns the binding
/// notification's <see cref="Value"/>. If not, returns the object unchanged.
/// </remarks>
public static object ExtractValue(object o)
{
var notification = o as BindingNotification;
return notification != null ? notification.Value : o;
}
/// <summary>
/// Compares an object to an instance of <see cref="BindingNotification"/> for equality.
/// </summary>

5
src/Avalonia.Base/Data/BindingOperations.cs

@ -54,7 +54,10 @@ namespace Avalonia.Data
if (source != null)
{
return source.Take(1).Subscribe(x => target.SetValue(property, x, binding.Priority));
return source
.Where(x => BindingNotification.ExtractValue(x) != AvaloniaProperty.UnsetValue)
.Take(1)
.Subscribe(x => target.SetValue(property, x, binding.Priority));
}
else
{

49
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Binding.cs

@ -54,6 +54,36 @@ namespace Avalonia.Base.UnitTests
Assert.False(target.IsSet(Class1.QuxProperty));
}
[Fact]
public void OneTime_Binding_Ignores_UnsetValue()
{
var target = new Class1();
var source = new Subject<object>();
target.Bind(Class1.QuxProperty, new TestOneTimeBinding(source));
source.OnNext(AvaloniaProperty.UnsetValue);
Assert.Equal(5.6, target.GetValue(Class1.QuxProperty));
source.OnNext(6.7);
Assert.Equal(6.7, target.GetValue(Class1.QuxProperty));
}
[Fact]
public void OneTime_Binding_Ignores_Binding_Errors()
{
var target = new Class1();
var source = new Subject<object>();
target.Bind(Class1.QuxProperty, new TestOneTimeBinding(source));
source.OnNext(new BindingNotification(new Exception(), BindingErrorType.Error));
Assert.Equal(5.6, target.GetValue(Class1.QuxProperty));
source.OnNext(6.7);
Assert.Equal(6.7, target.GetValue(Class1.QuxProperty));
}
[Fact]
public void Bind_Throws_Exception_For_Unregistered_Property()
{
@ -352,5 +382,24 @@ namespace Avalonia.Base.UnitTests
public static readonly StyledProperty<string> BarProperty =
AvaloniaProperty.Register<Class2, string>("Bar", "bardefault");
}
private class TestOneTimeBinding : IBinding
{
private IObservable<object> _source;
public TestOneTimeBinding(IObservable<object> source)
{
_source = source;
}
public InstancedBinding Initiate(
IAvaloniaObject target,
AvaloniaProperty targetProperty,
object anchor = null,
bool enableDataValidation = false)
{
return new InstancedBinding(_source, BindingMode.OneTime);
}
}
}
}

Loading…
Cancel
Save