diff --git a/src/Avalonia.Base/Animation/Animatable.cs b/src/Avalonia.Base/Animation/Animatable.cs
index b045a32cd1..edaa76233e 100644
--- a/src/Avalonia.Base/Animation/Animatable.cs
+++ b/src/Avalonia.Base/Animation/Animatable.cs
@@ -235,7 +235,7 @@ namespace Avalonia.Animation
private object? GetAnimationBaseValue(AvaloniaProperty property)
{
- var value = this.GetBaseValue(property, BindingPriority.LocalValue);
+ var value = this.GetBaseValue(property);
if (value == AvaloniaProperty.UnsetValue)
{
diff --git a/src/Avalonia.Base/Animation/AnimationInstance`1.cs b/src/Avalonia.Base/Animation/AnimationInstance`1.cs
index 52cd4b324f..0881fde988 100644
--- a/src/Avalonia.Base/Animation/AnimationInstance`1.cs
+++ b/src/Avalonia.Base/Animation/AnimationInstance`1.cs
@@ -229,7 +229,7 @@ namespace Avalonia.Animation
private void UpdateNeutralValue()
{
var property = _animator.Property ?? throw new InvalidOperationException("Animator has no property specified.");
- var baseValue = _targetControl.GetBaseValue(property, BindingPriority.LocalValue);
+ var baseValue = _targetControl.GetBaseValue(property);
_neutralValue = baseValue != AvaloniaProperty.UnsetValue ?
(T)baseValue! : (T)_targetControl.GetValue(property)!;
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index 15feed388b..b11a6027f2 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -34,6 +34,7 @@
+
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 6633eabb5d..60e7b2aeef 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -5,7 +5,6 @@ using Avalonia.Data;
using Avalonia.Diagnostics;
using Avalonia.Logging;
using Avalonia.PropertyStore;
-using Avalonia.Reactive;
using Avalonia.Threading;
namespace Avalonia
@@ -23,7 +22,7 @@ namespace Avalonia
private PropertyChangedEventHandler? _inpcChanged;
private EventHandler? _propertyChanged;
private List? _inheritanceChildren;
- private ValueStore? _values;
+ private ValueStore _values;
private bool _batchUpdate;
///
@@ -32,6 +31,7 @@ namespace Avalonia
public AvaloniaObject()
{
VerifyAccess();
+ _values = new ValueStore(this);
}
///
@@ -59,7 +59,7 @@ namespace Avalonia
///
/// The inheritance parent.
///
- protected AvaloniaObject? InheritanceParent
+ protected internal AvaloniaObject? InheritanceParent
{
get
{
@@ -77,23 +77,8 @@ namespace Avalonia
_inheritanceParent?.RemoveInheritanceChild(this);
_inheritanceParent = value;
-
- var properties = AvaloniaPropertyRegistry.Instance.GetRegisteredInherited(GetType());
- var propertiesCount = properties.Count;
-
- for (var i = 0; i < propertiesCount; i++)
- {
- var property = properties[i];
- if (valuestore?.IsSet(property) == true)
- {
- // If local value set there can be no change.
- continue;
- }
-
- property.RouteInheritanceParentChanged(this, oldParent);
- }
-
_inheritanceParent?.AddInheritanceChild(this);
+ _values.SetInheritanceParent(oldParent, value);
}
}
}
@@ -118,24 +103,15 @@ namespace Avalonia
set { this.Bind(binding.Property!, value); }
}
- private ValueStore Values
- {
- get
- {
- if (_values is null)
- {
- _values = new ValueStore(this);
-
- if (_batchUpdate)
- _values.BeginBatchUpdate();
- }
-
- return _values;
- }
- }
-
+ ///
+ /// Returns a value indicating whether the current thread is the UI thread.
+ ///
+ /// true if the current thread is the UI thread; otherwise false.
public bool CheckAccess() => Dispatcher.UIThread.CheckAccess();
+ ///
+ /// Checks that the current thread is the UI thread and throws if not.
+ ///
public void VerifyAccess() => Dispatcher.UIThread.VerifyAccess();
///
@@ -144,9 +120,9 @@ namespace Avalonia
/// The property.
public void ClearValue(AvaloniaProperty property)
{
- property = property ?? throw new ArgumentNullException(nameof(property));
-
- property.RouteClearValue(this);
+ _ = property ?? throw new ArgumentNullException(nameof(property));
+ VerifyAccess();
+ _values.ClearLocalValue(property);
}
///
@@ -232,12 +208,7 @@ namespace Avalonia
///
/// The property.
/// The value.
- public object? GetValue(AvaloniaProperty property)
- {
- property = property ?? throw new ArgumentNullException(nameof(property));
-
- return property.RouteGetValue(this);
- }
+ public object? GetValue(AvaloniaProperty property) => property.RouteGetValue(this);
///
/// Gets a value.
@@ -247,10 +218,9 @@ namespace Avalonia
/// The value.
public T GetValue(StyledPropertyBase property)
{
- property = property ?? throw new ArgumentNullException(nameof(property));
+ _ = property ?? throw new ArgumentNullException(nameof(property));
VerifyAccess();
-
- return GetValueOrInheritedOrDefault(property);
+ return _values.GetValue(property);
}
///
@@ -269,18 +239,10 @@ namespace Avalonia
}
///
- public Optional GetBaseValue(StyledPropertyBase property, BindingPriority maxPriority)
+ public Optional GetBaseValue(StyledPropertyBase property)
{
- property = property ?? throw new ArgumentNullException(nameof(property));
- VerifyAccess();
-
- if (_values is object &&
- _values.TryGetValue(property, maxPriority, out var value))
- {
- return value;
- }
-
- return default;
+ _ = property ?? throw new ArgumentNullException(nameof(property));
+ return _values.GetBaseValue(property);
}
///
@@ -346,26 +308,19 @@ namespace Avalonia
T value,
BindingPriority priority = BindingPriority.LocalValue)
{
- property = property ?? throw new ArgumentNullException(nameof(property));
+ _ = property ?? throw new ArgumentNullException(nameof(property));
VerifyAccess();
- LogPropertySet(property, value, priority);
+ LogPropertySet(property, value, BindingPriority.LocalValue);
if (value is UnsetValueType)
{
if (priority == BindingPriority.LocalValue)
- {
- Values.ClearLocalValue(property);
- }
- else
- {
- throw new NotSupportedException(
- "Cannot set property to Unset at non-local value priority.");
- }
+ _values.ClearLocalValue(property);
}
- else if (!(value is DoNothingType))
+ else if (value is not DoNothingType)
{
- return Values.SetValue(property, value, priority);
+ return _values.SetValue(property, value, priority);
}
return null;
@@ -389,6 +344,7 @@ namespace Avalonia
///
/// Binds a to an observable.
///
+ /// The type of the property.
/// The property.
/// The observable.
/// The priority of the binding.
@@ -398,12 +354,51 @@ namespace Avalonia
public IDisposable Bind(
AvaloniaProperty property,
IObservable