Browse Source

Remove empty frames.

In doing so, merged `ValueStore.OnBindingCompleted` into `OnValueEntryRemoved` as they were doing the same thing.
pull/8600/head
Steven Kirk 4 years ago
parent
commit
ae72b81af9
  1. 6
      src/Avalonia.Base/PropertyStore/ValueFrame.cs
  2. 29
      src/Avalonia.Base/PropertyStore/ValueStore.cs
  3. 20
      tests/Avalonia.Base.UnitTests/PropertyStore/ValueStoreTests_Frames.cs

6
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()

29
src/Avalonia.Base/PropertyStore/ValueStore.cs

@ -397,23 +397,6 @@ namespace Avalonia.PropertyStore
}
}
/// <summary>
/// Called by a <see cref="BindingEntryBase{TValue, TSource}"/> to re-evaluate the
/// effective value when the binding completes or terminates on error.
/// </summary>
/// <param name="property">The previously bound property.</param>
/// <param name="frame">The frame which contained the binding.</param>
public void OnBindingCompleted(AvaloniaProperty property, ValueFrame frame)
{
var priority = frame.Priority;
if (TryGetEffectiveValue(property, out var existing))
{
if (priority <= existing.Priority)
ReevaluateEffectiveValue(property, existing);
}
}
/// <summary>
/// Called by a <see cref="ValueFrame"/> when its <see cref="ValueFrame.IsActive"/>
/// state changes.
@ -577,22 +560,14 @@ namespace Avalonia.PropertyStore
/// <param name="property">The property whose value was removed.</param>
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)

20
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<PropertyChange>();
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<BindingValue<string>>("foo");
target.Bind(Class1.FooProperty, source, BindingPriority.Animation);
var valueStore = target.GetValueStore();
Assert.Equal(1, valueStore.Frames.Count);
Assert.IsType<ImmediateValueFrame>(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);

Loading…
Cancel
Save