From 3afa95253f0c517e85af08bcc6d1f3ea074e9ff3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 19 Mar 2021 13:38:29 +0100 Subject: [PATCH] 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 --- src/Avalonia.Base/ValueStore.cs | 6 ++++-- .../AvaloniaObjectTests_BatchUpdate.cs | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/ValueStore.cs b/src/Avalonia.Base/ValueStore.cs index 470be35592..9ece2b8042 100644 --- a/src/Avalonia.Base/ValueStore.cs +++ b/src/Avalonia.Base/ValueStore.cs @@ -138,7 +138,7 @@ namespace Avalonia IObservable> source, BindingPriority priority) { - if (_values.TryGetValue(property, out var slot)) + if (_values.TryGetValue(property, out var slot) && !IsRemoveSentinel(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) diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs index 5bf3afc9e7..036f275a71 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs +++ b/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(); target.Foo = "foo"; @@ -490,11 +491,16 @@ namespace Avalonia.Base.UnitTests target.Bind(TestClass.FooProperty, new TestObservable("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