Browse Source

Allow binding property during ending batch update.

- Allow adding a binding to a cleared property while ending a batch update. Need to check that the existing value isn't a remove sentinel here, otherwise the binding will be lost.
- When a binding is added during the end of a batch update, `_batchUpdate` will be non-null but newly added bindings shouldn't have `BeginBatchUpdate` called on them because no `EndBatchUpdate` will arrive (as we've already called them)
- Add sanity checks to the unit test to make sure that correct notifications are raised
pull/5686/head
Steven Kirk 5 years ago
parent
commit
3afa95253f
  1. 6
      src/Avalonia.Base/ValueStore.cs
  2. 6
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs

6
src/Avalonia.Base/ValueStore.cs

@ -138,7 +138,7 @@ namespace Avalonia
IObservable<BindingValue<T>> source,
BindingPriority priority)
{
if (_values.TryGetValue(property, out var slot))
if (_values.TryGetValue(property, out var slot) && !IsRemoveSentinel<T>(slot))
{
return BindExisting(slot, property, source, priority);
}
@ -338,7 +338,7 @@ namespace Avalonia
private void AddValue(AvaloniaProperty property, IValue value)
{
_values.AddValue(property, value);
if (_batchUpdate is object && value is IBatchUpdate batch)
if (_batchUpdate?.IsBatchUpdating == true && value is IBatchUpdate batch)
batch.BeginBatchUpdate();
value.Start();
}
@ -381,6 +381,8 @@ namespace Avalonia
public BatchUpdate(ValueStore owner) => _owner = owner;
public bool IsBatchUpdating => _batchUpdateCount > 0;
public void Begin()
{
if (_batchUpdateCount++ == 0)

6
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs

@ -478,6 +478,7 @@ namespace Avalonia.Base.UnitTests
{
var target = new TestClass();
var raised = 0;
var notifications = new List<AvaloniaPropertyChangedEventArgs>();
target.Foo = "foo";
@ -490,11 +491,16 @@ namespace Avalonia.Base.UnitTests
target.Bind(TestClass.FooProperty, new TestObservable<string>("bar"));
++raised;
}
notifications.Add(e);
};
target.EndBatchUpdate();
Assert.Equal("bar", target.Foo);
Assert.Equal(1, raised);
Assert.Equal(2, notifications.Count);
Assert.Equal(null, notifications[0].NewValue);
Assert.Equal("bar", notifications[1].NewValue);
}
public class TestClass : AvaloniaObject

Loading…
Cancel
Save