diff --git a/src/Avalonia.Base/PropertyStore/ValueFrame.cs b/src/Avalonia.Base/PropertyStore/ValueFrame.cs
index 90714ec5ac..5ada4b3c84 100644
--- a/src/Avalonia.Base/PropertyStore/ValueFrame.cs
+++ b/src/Avalonia.Base/PropertyStore/ValueFrame.cs
@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Data;
using Avalonia.Utilities;
+using static Avalonia.Rendering.Composition.Animations.PropertySetSnapshot;
namespace Avalonia.PropertyStore
{
@@ -45,8 +46,9 @@ namespace Avalonia.PropertyStore
public void OnBindingCompleted(IValueEntry binding)
{
- Remove(binding.Property);
- Owner?.OnBindingCompleted(binding.Property, this);
+ var property = binding.Property;
+ Remove(property);
+ Owner?.OnValueEntryRemoved(this, property);
}
public virtual void Dispose()
diff --git a/src/Avalonia.Base/PropertyStore/ValueStore.cs b/src/Avalonia.Base/PropertyStore/ValueStore.cs
index 8d7fae41bf..bbc71f1a38 100644
--- a/src/Avalonia.Base/PropertyStore/ValueStore.cs
+++ b/src/Avalonia.Base/PropertyStore/ValueStore.cs
@@ -397,23 +397,6 @@ namespace Avalonia.PropertyStore
}
}
- ///
- /// Called by a to re-evaluate the
- /// effective value when the binding completes or terminates on error.
- ///
- /// The previously bound property.
- /// The frame which contained the binding.
- public void OnBindingCompleted(AvaloniaProperty property, ValueFrame frame)
- {
- var priority = frame.Priority;
-
- if (TryGetEffectiveValue(property, out var existing))
- {
- if (priority <= existing.Priority)
- ReevaluateEffectiveValue(property, existing);
- }
- }
-
///
/// Called by a when its
/// state changes.
@@ -577,22 +560,14 @@ namespace Avalonia.PropertyStore
/// The property whose value was removed.
public void OnValueEntryRemoved(ValueFrame frame, AvaloniaProperty property)
{
- Debug.Assert(frame.IsActive);
+ if (frame.EntryCount == 0)
+ _frames.Remove(frame);
if (TryGetEffectiveValue(property, out var existing))
{
if (frame.Priority <= existing.Priority)
ReevaluateEffectiveValue(property, existing);
}
- else
- {
- Logger.TryGet(LogEventLevel.Error, LogArea.Property)?.Log(
- Owner,
- "Internal error: ValueStore.OnEntryRemoved called for {Property} " +
- "but no effective value was found.",
- property);
- Debug.Assert(false);
- }
}
public bool RemoveFrame(ValueFrame frame)
diff --git a/tests/Avalonia.Base.UnitTests/PropertyStore/ValueStoreTests_Frames.cs b/tests/Avalonia.Base.UnitTests/PropertyStore/ValueStoreTests_Frames.cs
index 48bc21dc5f..bb726a1d63 100644
--- a/tests/Avalonia.Base.UnitTests/PropertyStore/ValueStoreTests_Frames.cs
+++ b/tests/Avalonia.Base.UnitTests/PropertyStore/ValueStoreTests_Frames.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-using System.Reactive;
using System.Reactive.Subjects;
+using Avalonia.Data;
using Avalonia.PropertyStore;
using Avalonia.Styling;
using Microsoft.Reactive.Testing;
@@ -80,7 +80,6 @@ namespace Avalonia.Base.UnitTests.PropertyStore
var target = new Class1();
var scheduler = new TestScheduler();
var obs = scheduler.CreateColdObservable(OnNext(0, "bar"));
- var result = new List();
var style = new Style
{
Setters =
@@ -99,6 +98,23 @@ namespace Avalonia.Base.UnitTests.PropertyStore
Assert.NotEqual(Subscription.Infinite, obs.Subscriptions[0].Unsubscribe);
}
+ [Fact]
+ public void Completing_Binding_Removes_ImmediateValueFrame()
+ {
+ var target = new Class1();
+ var source = new BehaviorSubject>("foo");
+
+ target.Bind(Class1.FooProperty, source, BindingPriority.Animation);
+
+ var valueStore = target.GetValueStore();
+ Assert.Equal(1, valueStore.Frames.Count);
+ Assert.IsType(valueStore.Frames[0]);
+
+ source.OnCompleted();
+
+ Assert.Equal(0, valueStore.Frames.Count);
+ }
+
private static StyleInstance InstanceStyle(Style style, StyledElement target)
{
var result = new StyleInstance(style, null);