diff --git a/samples/SampleControls/HamburgerMenu/HamburgerMenu.cs b/samples/SampleControls/HamburgerMenu/HamburgerMenu.cs index bbfd3d87cab..ab61dcde916 100644 --- a/samples/SampleControls/HamburgerMenu/HamburgerMenu.cs +++ b/samples/SampleControls/HamburgerMenu/HamburgerMenu.cs @@ -43,14 +43,13 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) _splitView = e.NameScope.Find("PART_NavigationPane"); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == BoundsProperty && _splitView is not null) { - var oldBounds = change.OldValue.GetValueOrDefault(); - var newBounds = change.NewValue.GetValueOrDefault(); + var (oldBounds, newBounds) = change.GetOldAndNewValue(); EnsureSplitViewMode(oldBounds, newBounds); } } diff --git a/src/Avalonia.Base/Animation/Animatable.cs b/src/Avalonia.Base/Animation/Animatable.cs index 50fc5ac73bf..b045a32cd1e 100644 --- a/src/Avalonia.Base/Animation/Animatable.cs +++ b/src/Avalonia.Base/Animation/Animatable.cs @@ -87,12 +87,13 @@ protected void DisableTransitions() } } - protected sealed override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) + protected sealed override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) { if (change.Property == TransitionsProperty && change.IsEffectiveValueChange) { - var oldTransitions = change.OldValue.GetValueOrDefault(); - var newTransitions = change.NewValue.GetValueOrDefault(); + var e = (AvaloniaPropertyChangedEventArgs)change; + var oldTransitions = e.OldValue.GetValueOrDefault(); + var newTransitions = e.NewValue.GetValueOrDefault(); // When transitions are replaced, we add the new transitions before removing the old // transitions, so that when the old transition being disposed causes the value to diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index 437339d3b2c..bc1e95805fc 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -5,6 +5,7 @@ using Avalonia.Diagnostics; using Avalonia.Logging; using Avalonia.PropertyStore; +using Avalonia.Reactive; using Avalonia.Threading; namespace Avalonia @@ -15,13 +16,13 @@ namespace Avalonia /// /// This class is analogous to DependencyObject in WPF. /// - public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged, IValueSink + public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged { - private IAvaloniaObject? _inheritanceParent; + private AvaloniaObject? _inheritanceParent; private List? _directBindings; private PropertyChangedEventHandler? _inpcChanged; private EventHandler? _propertyChanged; - private List? _inheritanceChildren; + private List? _inheritanceChildren; private ValueStore? _values; private bool _batchUpdate; @@ -58,7 +59,7 @@ event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged /// /// The inheritance parent. /// - protected IAvaloniaObject? InheritanceParent + protected AvaloniaObject? InheritanceParent { get { @@ -320,14 +321,14 @@ public bool IsSet(AvaloniaProperty property) /// The property. /// The value. /// The priority of the value. - public void SetValue( + public IDisposable? SetValue( AvaloniaProperty property, object? value, BindingPriority priority = BindingPriority.LocalValue) { property = property ?? throw new ArgumentNullException(nameof(property)); - property.RouteSetValue(this, value, priority); + return property.RouteSetValue(this, value, priority); } /// @@ -385,6 +386,26 @@ public void SetValue(DirectPropertyBase property, T value) SetDirectValueUnchecked(property, value); } + /// + /// Binds a to an observable. + /// + /// The property. + /// The observable. + /// The priority of the binding. + /// + /// A disposable which can be used to terminate the binding. + /// + public IDisposable Bind( + AvaloniaProperty property, + IObservable source, + BindingPriority priority = BindingPriority.LocalValue) + { + property = property ?? throw new ArgumentNullException(nameof(property)); + source = source ?? throw new ArgumentNullException(nameof(source)); + + return property.RouteBind(this, source.ToBindingValue(), priority); + } + /// /// Binds a to an observable. /// @@ -445,9 +466,8 @@ public IDisposable Bind( /// /// Coerces the specified . /// - /// The type of the property. /// The property. - public void CoerceValue(StyledPropertyBase property) + public void CoerceValue(AvaloniaProperty property) { _values?.CoerceValue(property); } @@ -475,19 +495,19 @@ public void EndBatchUpdate() } /// - void IAvaloniaObject.AddInheritanceChild(IAvaloniaObject child) + internal void AddInheritanceChild(AvaloniaObject child) { - _inheritanceChildren ??= new List(); + _inheritanceChildren ??= new List(); _inheritanceChildren.Add(child); } /// - void IAvaloniaObject.RemoveInheritanceChild(IAvaloniaObject child) + internal void RemoveInheritanceChild(AvaloniaObject child) { _inheritanceChildren?.Remove(child); } - void IAvaloniaObject.InheritedPropertyChanged( + internal void InheritedPropertyChanged( AvaloniaProperty property, Optional oldValue, Optional newValue) @@ -504,7 +524,7 @@ void IAvaloniaObject.InheritedPropertyChanged( return _propertyChanged?.GetInvocationList(); } - void IValueSink.ValueChanged(AvaloniaPropertyChangedEventArgs change) + internal void ValueChanged(AvaloniaPropertyChangedEventArgs change) { var property = (StyledPropertyBase)change.Property; @@ -543,7 +563,7 @@ void IValueSink.ValueChanged(AvaloniaPropertyChangedEventArgs change) } } - void IValueSink.Completed( + internal void Completed( StyledPropertyBase property, IPriorityValueEntry entry, Optional oldValue) @@ -554,7 +574,7 @@ void IValueSink.Completed( oldValue, default, BindingPriority.Unset); - ((IValueSink)this).ValueChanged(change); + ValueChanged(change); } /// @@ -565,14 +585,11 @@ void IValueSink.Completed( /// The old inheritance parent. internal void InheritanceParentChanged( StyledPropertyBase property, - IAvaloniaObject? oldParent) + AvaloniaObject? oldParent) { - var oldValue = oldParent switch - { - AvaloniaObject o => o.GetValueOrInheritedOrDefault(property), - null => property.GetDefaultValue(GetType()), - _ => oldParent.GetValue(property) - }; + var oldValue = oldParent is not null ? + oldParent.GetValueOrInheritedOrDefault(property) : + property.GetDefaultValue(GetType()); var newValue = GetInheritedOrDefault(property); @@ -640,7 +657,7 @@ protected virtual void UpdateDataValidation( /// Called when a avalonia property changes on the object. /// /// The property change details. - protected virtual void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) + protected virtual void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) { if (change.IsEffectiveValueChange) { @@ -652,7 +669,7 @@ protected virtual void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs /// Called when a avalonia property changes on the object. /// /// The property change details. - protected virtual void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected virtual void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { } diff --git a/src/Avalonia.Base/AvaloniaObjectExtensions.cs b/src/Avalonia.Base/AvaloniaObjectExtensions.cs index 51237409bff..134e3b2ac7d 100644 --- a/src/Avalonia.Base/AvaloniaObjectExtensions.cs +++ b/src/Avalonia.Base/AvaloniaObjectExtensions.cs @@ -25,7 +25,7 @@ public static IBinding ToBinding(this IObservable source) } /// - /// Gets an observable for a . + /// Gets an observable for an . /// /// The object. /// The property. @@ -44,7 +44,7 @@ public static IBinding ToBinding(this IObservable source) } /// - /// Gets an observable for a . + /// Gets an observable for an . /// /// The object. /// The property type. @@ -64,7 +64,7 @@ public static IObservable GetObservable(this IAvaloniaObject o, AvaloniaPr } /// - /// Gets an observable for a . + /// Gets an observable for an . /// /// The object. /// The property. @@ -85,7 +85,7 @@ public static IObservable GetObservable(this IAvaloniaObject o, AvaloniaPr } /// - /// Gets an observable for a . + /// Gets an observable for an . /// /// The object. /// The property type. @@ -128,7 +128,7 @@ public static IObservable GetPropertyChangedOb } /// - /// Gets a subject for a . + /// Gets a subject for an . /// /// The object. /// The property. @@ -150,7 +150,7 @@ public static IObservable GetPropertyChangedOb } /// - /// Gets a subject for a . + /// Gets a subject for an . /// /// The property type. /// The object. @@ -230,30 +230,7 @@ public static ISubject> GetBindingSubject( } /// - /// Binds a to an observable. - /// - /// The object. - /// The property. - /// The observable. - /// The priority of the binding. - /// - /// A disposable which can be used to terminate the binding. - /// - public static IDisposable Bind( - this IAvaloniaObject target, - AvaloniaProperty property, - IObservable> source, - BindingPriority priority = BindingPriority.LocalValue) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - source = source ?? throw new ArgumentNullException(nameof(source)); - - return property.RouteBind(target, source, priority); - } - - /// - /// Binds a to an observable. + /// Binds an to an observable. /// /// The type of the property. /// The object. @@ -273,42 +250,22 @@ public static IDisposable Bind( property = property ?? throw new ArgumentNullException(nameof(property)); source = source ?? throw new ArgumentNullException(nameof(source)); - return property switch + if (target is AvaloniaObject ao) { - StyledPropertyBase styled => target.Bind(styled, source, priority), - DirectPropertyBase direct => target.Bind(direct, source), - _ => throw new NotSupportedException("Unsupported AvaloniaProperty type."), - }; - } + return property switch + { + StyledPropertyBase styled => ao.Bind(styled, source, priority), + DirectPropertyBase direct => ao.Bind(direct, source), + _ => throw new NotSupportedException("Unsupported AvaloniaProperty type."), + }; + } - /// - /// Binds a to an observable. - /// - /// The object. - /// The property. - /// The observable. - /// The priority of the binding. - /// - /// A disposable which can be used to terminate the binding. - /// - public static IDisposable Bind( - this IAvaloniaObject target, - AvaloniaProperty property, - IObservable source, - BindingPriority priority = BindingPriority.LocalValue) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - source = source ?? throw new ArgumentNullException(nameof(source)); + throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported."); - return target.Bind( - property, - source.ToBindingValue(), - priority); } /// - /// Binds a to an observable. + /// Binds an to an observable. /// /// The object. /// The property. @@ -334,7 +291,7 @@ public static IDisposable Bind( } /// - /// Binds a property on an to an . + /// Binds a property on an to an . /// /// The object. /// The property to bind. @@ -374,56 +331,6 @@ public static IDisposable Bind( } } - /// - /// Clears a 's local value. - /// - /// The object. - /// The property. - public static void ClearValue(this IAvaloniaObject target, AvaloniaProperty property) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - - property.RouteClearValue(target); - } - - /// - /// Clears a 's local value. - /// - /// The object. - /// The property. - public static void ClearValue(this IAvaloniaObject target, AvaloniaProperty property) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - - switch (property) - { - case StyledPropertyBase styled: - target.ClearValue(styled); - break; - case DirectPropertyBase direct: - target.ClearValue(direct); - break; - default: - throw new NotSupportedException("Unsupported AvaloniaProperty type."); - } - } - - /// - /// Gets a value. - /// - /// The object. - /// The property. - /// The value. - public static object? GetValue(this IAvaloniaObject target, AvaloniaProperty property) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - - return property.RouteGetValue(target); - } - /// /// Gets a value. /// @@ -436,12 +343,18 @@ public static T GetValue(this IAvaloniaObject target, AvaloniaProperty pro target = target ?? throw new ArgumentNullException(nameof(target)); property = property ?? throw new ArgumentNullException(nameof(property)); - return property switch + if (target is AvaloniaObject ao) { - StyledPropertyBase styled => target.GetValue(styled), - DirectPropertyBase direct => target.GetValue(direct), - _ => throw new NotSupportedException("Unsupported AvaloniaProperty type.") - }; + return property switch + { + StyledPropertyBase styled => ao.GetValue(styled), + DirectPropertyBase direct => ao.GetValue(direct), + _ => throw new NotSupportedException("Unsupported AvaloniaProperty type.") + }; + + } + + throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported."); } /// @@ -456,7 +369,7 @@ public static T GetValue(this IAvaloniaObject target, AvaloniaProperty pro /// . Note that this method does not return /// property values that come from inherited or default values. /// - /// For direct properties returns . + /// For direct properties returns the current value of the property. /// public static object? GetBaseValue( this IAvaloniaObject target, @@ -466,7 +379,9 @@ public static T GetValue(this IAvaloniaObject target, AvaloniaProperty pro target = target ?? throw new ArgumentNullException(nameof(target)); property = property ?? throw new ArgumentNullException(nameof(property)); - return property.RouteGetBaseValue(target, maxPriority); + if (target is AvaloniaObject ao) + return property.RouteGetBaseValue(ao, maxPriority); + throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported."); } /// @@ -481,8 +396,7 @@ public static T GetValue(this IAvaloniaObject target, AvaloniaProperty pro /// . Note that this method does not return property values /// that come from inherited or default values. /// - /// For direct properties returns - /// . + /// For direct properties returns the current value of the property. /// public static Optional GetBaseValue( this IAvaloniaObject target, @@ -492,69 +406,18 @@ public static Optional GetBaseValue( target = target ?? throw new ArgumentNullException(nameof(target)); property = property ?? throw new ArgumentNullException(nameof(property)); - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - - return property switch + if (target is AvaloniaObject ao) { - StyledPropertyBase styled => target.GetBaseValue(styled, maxPriority), - DirectPropertyBase direct => target.GetValue(direct), - _ => throw new NotSupportedException("Unsupported AvaloniaProperty type.") - }; - } - - /// - /// Sets a value. - /// - /// The object. - /// The property. - /// The value. - /// The priority of the value. - /// - /// An if setting the property can be undone, otherwise null. - /// - public static IDisposable? SetValue( - this IAvaloniaObject target, - AvaloniaProperty property, - object? value, - BindingPriority priority = BindingPriority.LocalValue) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); - - return property.RouteSetValue(target, value, priority); - } - - /// - /// Sets a value. - /// - /// The type of the property. - /// The object. - /// The property. - /// The value. - /// The priority of the value. - /// - /// An if setting the property can be undone, otherwise null. - /// - public static IDisposable? SetValue( - this IAvaloniaObject target, - AvaloniaProperty property, - T value, - BindingPriority priority = BindingPriority.LocalValue) - { - target = target ?? throw new ArgumentNullException(nameof(target)); - property = property ?? throw new ArgumentNullException(nameof(property)); + return property switch + { + StyledPropertyBase styled => ao.GetBaseValue(styled, maxPriority), + DirectPropertyBase direct => ao.GetValue(direct), + _ => throw new NotSupportedException("Unsupported AvaloniaProperty type.") + }; - switch (property) - { - case StyledPropertyBase styled: - return target.SetValue(styled, value, priority); - case DirectPropertyBase direct: - target.SetValue(direct, value); - return null; - default: - throw new NotSupportedException("Unsupported AvaloniaProperty type."); } + + throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported."); } /// @@ -622,17 +485,6 @@ public static IDisposable AddClassHandler( return observable.Subscribe(e => SubscribeAdapter(e, handler)); } - /// - /// Gets a description of a property that van be used in observables. - /// - /// The object. - /// The property - /// The description. - private static string GetDescription(IAvaloniaObject o, AvaloniaProperty property) - { - return $"{o.GetType().Name}.{property.Name}"; - } - /// /// Observer method for . diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs index 3d1e898f501..62ca971412e 100644 --- a/src/Avalonia.Base/AvaloniaProperty.cs +++ b/src/Avalonia.Base/AvaloniaProperty.cs @@ -467,20 +467,20 @@ public abstract void Accept(IAvaloniaPropertyVisitor visitor, ref /// Routes an untyped ClearValue call to a typed call. /// /// The object instance. - internal abstract void RouteClearValue(IAvaloniaObject o); + internal abstract void RouteClearValue(AvaloniaObject o); /// /// Routes an untyped GetValue call to a typed call. /// /// The object instance. - internal abstract object? RouteGetValue(IAvaloniaObject o); + internal abstract object? RouteGetValue(AvaloniaObject o); /// /// Routes an untyped GetBaseValue call to a typed call. /// /// The object instance. /// The maximum priority for the value. - internal abstract object? RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority); + internal abstract object? RouteGetBaseValue(AvaloniaObject o, BindingPriority maxPriority); /// /// Routes an untyped SetValue call to a typed call. @@ -492,7 +492,7 @@ public abstract void Accept(IAvaloniaPropertyVisitor visitor, ref /// An if setting the property can be undone, otherwise null. /// internal abstract IDisposable? RouteSetValue( - IAvaloniaObject o, + AvaloniaObject o, object? value, BindingPriority priority); @@ -503,11 +503,11 @@ public abstract void Accept(IAvaloniaPropertyVisitor visitor, ref /// The binding source. /// The priority. internal abstract IDisposable RouteBind( - IAvaloniaObject o, + AvaloniaObject o, IObservable> source, BindingPriority priority); - internal abstract void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject? oldParent); + internal abstract void RouteInheritanceParentChanged(AvaloniaObject o, AvaloniaObject? oldParent); /// /// Overrides the metadata for the property on the specified type. diff --git a/src/Avalonia.Base/AvaloniaPropertyChangedExtensions.cs b/src/Avalonia.Base/AvaloniaPropertyChangedExtensions.cs new file mode 100644 index 00000000000..a52d6d15aba --- /dev/null +++ b/src/Avalonia.Base/AvaloniaPropertyChangedExtensions.cs @@ -0,0 +1,43 @@ +namespace Avalonia +{ + /// + /// Provides extensions for . + /// + public static class AvaloniaPropertyChangedExtensions + { + /// + /// Gets a typed value from . + /// + /// The value type. + /// The event args. + /// The value. + public static T GetOldValue(this AvaloniaPropertyChangedEventArgs e) + { + return ((AvaloniaPropertyChangedEventArgs)e).OldValue.GetValueOrDefault()!; + } + + /// + /// Gets a typed value from . + /// + /// The value type. + /// The event args. + /// The value. + public static T GetNewValue(this AvaloniaPropertyChangedEventArgs e) + { + return ((AvaloniaPropertyChangedEventArgs)e).NewValue.GetValueOrDefault()!; + } + + /// + /// Gets a typed value from and + /// . + /// + /// The value type. + /// The event args. + /// The value. + public static (T oldValue, T newValue) GetOldAndNewValue(this AvaloniaPropertyChangedEventArgs e) + { + var ev = (AvaloniaPropertyChangedEventArgs)e; + return (ev.OldValue.GetValueOrDefault()!, ev.NewValue.GetValueOrDefault()!); + } + } +} diff --git a/src/Avalonia.Base/DirectPropertyBase.cs b/src/Avalonia.Base/DirectPropertyBase.cs index 9c4896b96c4..6e3baea99b7 100644 --- a/src/Avalonia.Base/DirectPropertyBase.cs +++ b/src/Avalonia.Base/DirectPropertyBase.cs @@ -127,25 +127,25 @@ public override void Accept(IAvaloniaPropertyVisitor visitor, ref } /// - internal override void RouteClearValue(IAvaloniaObject o) + internal override void RouteClearValue(AvaloniaObject o) { o.ClearValue(this); } /// - internal override object? RouteGetValue(IAvaloniaObject o) + internal override object? RouteGetValue(AvaloniaObject o) { return o.GetValue(this); } - internal override object? RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority) + internal override object? RouteGetBaseValue(AvaloniaObject o, BindingPriority maxPriority) { return o.GetValue(this); } /// internal override IDisposable? RouteSetValue( - IAvaloniaObject o, + AvaloniaObject o, object? value, BindingPriority priority) { @@ -169,7 +169,7 @@ internal override void RouteClearValue(IAvaloniaObject o) /// internal override IDisposable RouteBind( - IAvaloniaObject o, + AvaloniaObject o, IObservable> source, BindingPriority priority) { @@ -177,7 +177,7 @@ internal override IDisposable RouteBind( return o.Bind(this, adapter); } - internal override void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject? oldParent) + internal override void RouteInheritanceParentChanged(AvaloniaObject o, AvaloniaObject? oldParent) { throw new NotSupportedException("Direct properties do not support inheritance."); } diff --git a/src/Avalonia.Base/GeometryGroup.cs b/src/Avalonia.Base/GeometryGroup.cs index c6b666b2eb7..b90c9c6d8a4 100644 --- a/src/Avalonia.Base/GeometryGroup.cs +++ b/src/Avalonia.Base/GeometryGroup.cs @@ -68,7 +68,7 @@ public override Geometry Clone() return null; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Base/IAvaloniaObject.cs b/src/Avalonia.Base/IAvaloniaObject.cs index 654528658fb..00f5062f9e5 100644 --- a/src/Avalonia.Base/IAvaloniaObject.cs +++ b/src/Avalonia.Base/IAvaloniaObject.cs @@ -17,42 +17,14 @@ public interface IAvaloniaObject /// Clears an 's local value. /// /// The property. - void ClearValue(StyledPropertyBase property); - - /// - /// Clears an 's local value. - /// - /// The property. - void ClearValue(DirectPropertyBase property); - - /// - /// Gets a value. - /// - /// The type of the property. - /// The property. - /// The value. - T GetValue(StyledPropertyBase property); + void ClearValue(AvaloniaProperty property); /// /// Gets a value. /// - /// The type of the property. /// The property. /// The value. - T GetValue(DirectPropertyBase property); - - /// - /// Gets an base value. - /// - /// The type of the property. - /// The property. - /// The maximum priority for the value. - /// - /// Gets the value of the property, if set on this object with a priority equal or lower to - /// , otherwise . Note that - /// this method does not return property values that come from inherited or default values. - /// - Optional GetBaseValue(StyledPropertyBase property, BindingPriority maxPriority); + object? GetValue(AvaloniaProperty property); /// /// Checks whether a is animating. @@ -71,93 +43,35 @@ public interface IAvaloniaObject /// /// Sets a value. /// - /// The type of the property. /// The property. /// The value. /// The priority of the value. /// /// An if setting the property can be undone, otherwise null. /// - IDisposable? SetValue( - StyledPropertyBase property, - T value, + IDisposable? SetValue( + AvaloniaProperty property, + object? value, BindingPriority priority = BindingPriority.LocalValue); - /// - /// Sets a value. - /// - /// The type of the property. - /// The property. - /// The value. - void SetValue(DirectPropertyBase property, T value); - /// /// Binds a to an observable. /// - /// The type of the property. /// The property. /// The observable. /// The priority of the binding. /// /// A disposable which can be used to terminate the binding. /// - IDisposable Bind( - StyledPropertyBase property, - IObservable> source, + IDisposable Bind( + AvaloniaProperty property, + IObservable source, BindingPriority priority = BindingPriority.LocalValue); - /// - /// Binds a to an observable. - /// - /// The type of the property. - /// The property. - /// The observable. - /// - /// A disposable which can be used to terminate the binding. - /// - IDisposable Bind( - DirectPropertyBase property, - IObservable> source); - /// /// Coerces the specified . /// - /// The type of the property. /// The property. - void CoerceValue(StyledPropertyBase property); - - /// - /// Registers an object as an inheritance child. - /// - /// The inheritance child. - /// - /// Inheritance children will receive a call to - /// - /// when an inheritable property value changes on the parent. - /// - void AddInheritanceChild(IAvaloniaObject child); - - /// - /// Unregisters an object as an inheritance child. - /// - /// The inheritance child. - /// - /// Removes an inheritance child that was added by a call to - /// . - /// - void RemoveInheritanceChild(IAvaloniaObject child); - - /// - /// Called when an inheritable property changes on an object registered as an inheritance - /// parent. - /// - /// The type of the value. - /// The property that has changed. - /// - /// - void InheritedPropertyChanged( - AvaloniaProperty property, - Optional oldValue, - Optional newValue); + void CoerceValue(AvaloniaProperty property); } } diff --git a/src/Avalonia.Base/Input/InputElement.cs b/src/Avalonia.Base/Input/InputElement.cs index 6bc9294ddd2..9fe07f62ddc 100644 --- a/src/Avalonia.Base/Input/InputElement.cs +++ b/src/Avalonia.Base/Input/InputElement.cs @@ -601,21 +601,21 @@ protected virtual void OnPointerWheelChanged(PointerWheelEventArgs e) { } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == IsFocusedProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault(), null); + UpdatePseudoClasses(change.GetNewValue(), null); } else if (change.Property == IsPointerOverProperty) { - UpdatePseudoClasses(null, change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(null, change.GetNewValue()); } else if (change.Property == IsKeyboardFocusWithinProperty) { - PseudoClasses.Set(":focus-within", change.NewValue.GetValueOrDefault()); + PseudoClasses.Set(":focus-within", change.GetNewValue()); } } diff --git a/src/Avalonia.Base/Input/KeyboardNavigation.cs b/src/Avalonia.Base/Input/KeyboardNavigation.cs index a25aed6811a..042a9adf5fb 100644 --- a/src/Avalonia.Base/Input/KeyboardNavigation.cs +++ b/src/Avalonia.Base/Input/KeyboardNavigation.cs @@ -58,7 +58,7 @@ public static class KeyboardNavigation /// The for the container. public static int GetTabIndex(IInputElement element) { - return ((IAvaloniaObject)element).GetValue(TabIndexProperty); + return ((AvaloniaObject)element).GetValue(TabIndexProperty); } /// diff --git a/src/Avalonia.Base/Input/Navigation/TabNavigation.cs b/src/Avalonia.Base/Input/Navigation/TabNavigation.cs index c8290cb3b79..cfd45f82628 100644 --- a/src/Avalonia.Base/Input/Navigation/TabNavigation.cs +++ b/src/Avalonia.Base/Input/Navigation/TabNavigation.cs @@ -610,7 +610,7 @@ internal static class TabNavigation private static IInputElement? GetActiveElement(IInputElement e) { - return ((IAvaloniaObject)e).GetValue(KeyboardNavigation.TabOnceActiveElementProperty); + return ((AvaloniaObject)e).GetValue(KeyboardNavigation.TabOnceActiveElementProperty); } private static IInputElement GetGroupParent(IInputElement e) => GetGroupParent(e, false); @@ -655,8 +655,9 @@ private static IInputElement GetGroupParent(IInputElement element, bool includeC private static KeyboardNavigationMode GetKeyNavigationMode(IInputElement e) { - return ((IAvaloniaObject)e).GetValue(KeyboardNavigation.TabNavigationProperty); + return ((AvaloniaObject)e).GetValue(KeyboardNavigation.TabNavigationProperty); } + private static bool IsFocusScope(IInputElement e) => FocusManager.GetIsFocusScope(e) || GetParent(e) == null; private static bool IsGroup(IInputElement e) => GetKeyNavigationMode(e) != KeyboardNavigationMode.Continue; diff --git a/src/Avalonia.Base/Layout/StackLayout.cs b/src/Avalonia.Base/Layout/StackLayout.cs index c63fe5e405f..00ac4a37f0a 100644 --- a/src/Avalonia.Base/Layout/StackLayout.cs +++ b/src/Avalonia.Base/Layout/StackLayout.cs @@ -320,11 +320,11 @@ protected internal override void OnItemsChangedCore(VirtualizingLayoutContext co InvalidateLayout(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Property == OrientationProperty) { - var orientation = change.NewValue.GetValueOrDefault(); + var orientation = change.GetNewValue(); //Note: For StackLayout Vertical Orientation means we have a Vertical ScrollOrientation. //Horizontal Orientation means we have a Horizontal ScrollOrientation. diff --git a/src/Avalonia.Base/Layout/UniformGridLayout.cs b/src/Avalonia.Base/Layout/UniformGridLayout.cs index 3b82ece886c..418cd55e41b 100644 --- a/src/Avalonia.Base/Layout/UniformGridLayout.cs +++ b/src/Avalonia.Base/Layout/UniformGridLayout.cs @@ -471,11 +471,11 @@ protected internal override void OnItemsChangedCore(VirtualizingLayoutContext co gridState.ClearElementOnDataSourceChange(context, args); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Property == OrientationProperty) { - var orientation = change.NewValue.GetValueOrDefault(); + var orientation = change.GetNewValue(); //Note: For UniformGridLayout Vertical Orientation means we have a Horizontal ScrollOrientation. Horizontal Orientation means we have a Vertical ScrollOrientation. //i.e. the properties are the inverse of each other. @@ -484,31 +484,31 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == MinColumnSpacingProperty) { - _minColumnSpacing = change.NewValue.GetValueOrDefault(); + _minColumnSpacing = change.GetNewValue(); } else if (change.Property == MinRowSpacingProperty) { - _minRowSpacing = change.NewValue.GetValueOrDefault(); + _minRowSpacing = change.GetNewValue(); } else if (change.Property == ItemsJustificationProperty) { - _itemsJustification = change.NewValue.GetValueOrDefault(); + _itemsJustification = change.GetNewValue(); } else if (change.Property == ItemsStretchProperty) { - _itemsStretch = change.NewValue.GetValueOrDefault(); + _itemsStretch = change.GetNewValue(); } else if (change.Property == MinItemWidthProperty) { - _minItemWidth = change.NewValue.GetValueOrDefault(); + _minItemWidth = change.GetNewValue(); } else if (change.Property == MinItemHeightProperty) { - _minItemHeight = change.NewValue.GetValueOrDefault(); + _minItemHeight = change.GetNewValue(); } else if (change.Property == MaximumRowsOrColumnsProperty) { - _maximumRowsOrColumns = change.NewValue.GetValueOrDefault(); + _maximumRowsOrColumns = change.GetNewValue(); } InvalidateLayout(); diff --git a/src/Avalonia.Base/Layout/WrapLayout/WrapLayout.cs b/src/Avalonia.Base/Layout/WrapLayout/WrapLayout.cs index aab0272f37b..52de1dd3b86 100644 --- a/src/Avalonia.Base/Layout/WrapLayout/WrapLayout.cs +++ b/src/Avalonia.Base/Layout/WrapLayout/WrapLayout.cs @@ -322,7 +322,7 @@ bool Arrange(WrapItem item, bool isLast = false) return finalSize; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Base/Media/DashStyle.cs b/src/Avalonia.Base/Media/DashStyle.cs index 2ec9436ede0..abee580020f 100644 --- a/src/Avalonia.Base/Media/DashStyle.cs +++ b/src/Avalonia.Base/Media/DashStyle.cs @@ -112,14 +112,13 @@ public double Offset /// public ImmutableDashStyle ToImmutable() => new ImmutableDashStyle(Dashes, Offset); - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == DashesProperty) { - var oldValue = change.OldValue.GetValueOrDefault>(); - var newValue = change.NewValue.GetValueOrDefault>(); + var (oldValue, newValue) = change.GetOldAndNewValue>(); if (oldValue is object) { diff --git a/src/Avalonia.Base/Media/DrawingImage.cs b/src/Avalonia.Base/Media/DrawingImage.cs index 1663e384b58..38ddbdfaed7 100644 --- a/src/Avalonia.Base/Media/DrawingImage.cs +++ b/src/Avalonia.Base/Media/DrawingImage.cs @@ -69,7 +69,7 @@ void IImage.Draw( } /// - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Base/Media/Pen.cs b/src/Avalonia.Base/Media/Pen.cs index bda0e5cb994..66632a973b6 100644 --- a/src/Avalonia.Base/Media/Pen.cs +++ b/src/Avalonia.Base/Media/Pen.cs @@ -193,7 +193,7 @@ public ImmutablePen ToImmutable() MiterLimit); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { _invalidated?.Invoke(this, EventArgs.Empty); if(change.Property == BrushProperty) diff --git a/src/Avalonia.Base/PropertyStore/BindingEntry.cs b/src/Avalonia.Base/PropertyStore/BindingEntry.cs index cffbaed6b02..9a25e98a23b 100644 --- a/src/Avalonia.Base/PropertyStore/BindingEntry.cs +++ b/src/Avalonia.Base/PropertyStore/BindingEntry.cs @@ -18,19 +18,19 @@ internal interface IBindingEntry : IBatchUpdate, IPriorityValueEntry, IDisposabl /// The property type. internal class BindingEntry : IBindingEntry, IPriorityValueEntry, IObserver> { - private readonly IAvaloniaObject _owner; - private IValueSink _sink; + private readonly AvaloniaObject _owner; + private ValueOwner _sink; private IDisposable? _subscription; private bool _isSubscribed; private bool _batchUpdate; private Optional _value; public BindingEntry( - IAvaloniaObject owner, + AvaloniaObject owner, StyledPropertyBase property, IObservable> source, BindingPriority priority, - IValueSink sink) + ValueOwner sink) { _owner = owner; Property = property; @@ -50,7 +50,7 @@ public void EndBatchUpdate() { _batchUpdate = false; - if (_sink is ValueStore) + if (_sink.IsValueStore) Start(); } @@ -113,16 +113,15 @@ public void Start(bool ignoreBatchUpdate) } } - public void Reparent(IValueSink sink) => _sink = sink; + public void Reparent(PriorityValue parent) => _sink = new(parent); public void RaiseValueChanged( - IValueSink sink, - IAvaloniaObject owner, + AvaloniaObject owner, AvaloniaProperty property, Optional oldValue, Optional newValue) { - sink.ValueChanged(new AvaloniaPropertyChangedEventArgs( + owner.ValueChanged(new AvaloniaPropertyChangedEventArgs( owner, (AvaloniaProperty)property, oldValue.Cast(), diff --git a/src/Avalonia.Base/PropertyStore/ConstantValueEntry.cs b/src/Avalonia.Base/PropertyStore/ConstantValueEntry.cs index c7fbf56abc0..4116f4abd9f 100644 --- a/src/Avalonia.Base/PropertyStore/ConstantValueEntry.cs +++ b/src/Avalonia.Base/PropertyStore/ConstantValueEntry.cs @@ -18,14 +18,14 @@ internal interface IConstantValueEntry : IPriorityValueEntry, IDisposable /// The property type. internal class ConstantValueEntry : IPriorityValueEntry, IConstantValueEntry { - private IValueSink _sink; + private ValueOwner _sink; private Optional _value; public ConstantValueEntry( StyledPropertyBase property, T value, BindingPriority priority, - IValueSink sink) + ValueOwner sink) { Property = property; _value = value; @@ -37,7 +37,7 @@ public ConstantValueEntry( StyledPropertyBase property, Optional value, BindingPriority priority, - IValueSink sink) + ValueOwner sink) { Property = property; _value = value; @@ -62,17 +62,16 @@ public void Dispose() _sink.Completed(Property, this, oldValue); } - public void Reparent(IValueSink sink) => _sink = sink; + public void Reparent(PriorityValue sink) => _sink = new(sink); public void Start() { } public void RaiseValueChanged( - IValueSink sink, - IAvaloniaObject owner, + AvaloniaObject owner, AvaloniaProperty property, Optional oldValue, Optional newValue) { - sink.ValueChanged(new AvaloniaPropertyChangedEventArgs( + owner.ValueChanged(new AvaloniaPropertyChangedEventArgs( owner, (AvaloniaProperty)property, oldValue.Cast(), diff --git a/src/Avalonia.Base/PropertyStore/IPriorityValueEntry.cs b/src/Avalonia.Base/PropertyStore/IPriorityValueEntry.cs index 26665ab6835..45bbd0cda5b 100644 --- a/src/Avalonia.Base/PropertyStore/IPriorityValueEntry.cs +++ b/src/Avalonia.Base/PropertyStore/IPriorityValueEntry.cs @@ -5,7 +5,6 @@ /// internal interface IPriorityValueEntry : IValue { - void Reparent(IValueSink sink); } /// @@ -14,5 +13,6 @@ internal interface IPriorityValueEntry : IValue /// The property type. internal interface IPriorityValueEntry : IPriorityValueEntry, IValue { + void Reparent(PriorityValue parent); } } diff --git a/src/Avalonia.Base/PropertyStore/IValue.cs b/src/Avalonia.Base/PropertyStore/IValue.cs index a4ec06e64e7..b493df92e62 100644 --- a/src/Avalonia.Base/PropertyStore/IValue.cs +++ b/src/Avalonia.Base/PropertyStore/IValue.cs @@ -11,8 +11,7 @@ internal interface IValue Optional GetValue(); void Start(); void RaiseValueChanged( - IValueSink sink, - IAvaloniaObject owner, + AvaloniaObject owner, AvaloniaProperty property, Optional oldValue, Optional newValue); diff --git a/src/Avalonia.Base/PropertyStore/IValueSink.cs b/src/Avalonia.Base/PropertyStore/IValueSink.cs deleted file mode 100644 index 738fdef267c..00000000000 --- a/src/Avalonia.Base/PropertyStore/IValueSink.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Avalonia.Data; - -namespace Avalonia.PropertyStore -{ - /// - /// Represents an entity that can receive change notifications in a . - /// - internal interface IValueSink - { - void ValueChanged(AvaloniaPropertyChangedEventArgs change); - - void Completed( - StyledPropertyBase property, - IPriorityValueEntry entry, - Optional oldValue); - } -} diff --git a/src/Avalonia.Base/PropertyStore/LocalValueEntry.cs b/src/Avalonia.Base/PropertyStore/LocalValueEntry.cs index cb5f3556d16..13ca69681f1 100644 --- a/src/Avalonia.Base/PropertyStore/LocalValueEntry.cs +++ b/src/Avalonia.Base/PropertyStore/LocalValueEntry.cs @@ -25,13 +25,12 @@ public Optional GetValue(BindingPriority maxPriority) public void Start() { } public void RaiseValueChanged( - IValueSink sink, - IAvaloniaObject owner, + AvaloniaObject owner, AvaloniaProperty property, Optional oldValue, Optional newValue) { - sink.ValueChanged(new AvaloniaPropertyChangedEventArgs( + owner.ValueChanged(new AvaloniaPropertyChangedEventArgs( owner, (AvaloniaProperty)property, oldValue.Cast(), diff --git a/src/Avalonia.Base/PropertyStore/PriorityValue.cs b/src/Avalonia.Base/PropertyStore/PriorityValue.cs index f670160e75b..112cf6619f3 100644 --- a/src/Avalonia.Base/PropertyStore/PriorityValue.cs +++ b/src/Avalonia.Base/PropertyStore/PriorityValue.cs @@ -1,10 +1,17 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using Avalonia.Data; namespace Avalonia.PropertyStore { + /// + /// Represents an untyped interface to . + /// + interface IPriorityValue : IValue + { + void UpdateEffectiveValue(); + } + /// /// Stores a set of prioritized values and bindings in a . /// @@ -16,10 +23,10 @@ namespace Avalonia.PropertyStore /// entries (sorted first by priority and then in the order /// they were added) plus a local value. /// - internal class PriorityValue : IValue, IValueSink, IBatchUpdate + internal class PriorityValue : IPriorityValue, IValue, IBatchUpdate { - private readonly IAvaloniaObject _owner; - private readonly IValueSink _sink; + private readonly AvaloniaObject _owner; + private readonly ValueStore _store; private readonly List> _entries = new List>(); private readonly Func? _coerceValue; private Optional _localValue; @@ -28,13 +35,13 @@ internal class PriorityValue : IValue, IValueSink, IBatchUpdate private bool _batchUpdate; public PriorityValue( - IAvaloniaObject owner, + AvaloniaObject owner, StyledPropertyBase property, - IValueSink sink) + ValueStore store) { _owner = owner; Property = property; - _sink = sink; + _store = store; if (property.HasCoercion) { @@ -44,11 +51,11 @@ public PriorityValue( } public PriorityValue( - IAvaloniaObject owner, + AvaloniaObject owner, StyledPropertyBase property, - IValueSink sink, + ValueStore store, IPriorityValueEntry existing) - : this(owner, property, sink) + : this(owner, property, store) { existing.Reparent(this); _entries.Add(existing); @@ -75,9 +82,9 @@ public PriorityValue( } public PriorityValue( - IAvaloniaObject owner, + AvaloniaObject owner, StyledPropertyBase property, - IValueSink sink, + ValueStore sink, LocalValueEntry existing) : this(owner, property, sink) { @@ -148,7 +155,7 @@ public Optional GetValue(BindingPriority maxPriority = BindingPriority.Animat else { var insert = FindInsertPoint(priority); - var entry = new ConstantValueEntry(Property, value, priority, this); + var entry = new ConstantValueEntry(Property, value, priority, new ValueOwner(this)); _entries.Insert(insert, entry); result = entry; } @@ -165,7 +172,7 @@ public Optional GetValue(BindingPriority maxPriority = BindingPriority.Animat public BindingEntry AddBinding(IObservable> source, BindingPriority priority) { - var binding = new BindingEntry(_owner, Property, source, priority, this); + var binding = new BindingEntry(_owner, Property, source, priority, new(this)); var insert = FindInsertPoint(binding.Priority); _entries.Insert(insert, binding); @@ -186,13 +193,12 @@ public BindingEntry AddBinding(IObservable> source, BindingPr public void Start() => UpdateEffectiveValue(null); public void RaiseValueChanged( - IValueSink sink, - IAvaloniaObject owner, + AvaloniaObject owner, AvaloniaProperty property, Optional oldValue, Optional newValue) { - sink.ValueChanged(new AvaloniaPropertyChangedEventArgs( + owner.ValueChanged(new AvaloniaPropertyChangedEventArgs( owner, (AvaloniaProperty)property, oldValue.Cast(), @@ -200,7 +206,7 @@ public void RaiseValueChanged( Priority)); } - void IValueSink.ValueChanged(AvaloniaPropertyChangedEventArgs change) + public void ValueChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Priority == BindingPriority.LocalValue) { @@ -213,22 +219,15 @@ void IValueSink.ValueChanged(AvaloniaPropertyChangedEventArgs ch } } - void IValueSink.Completed( - StyledPropertyBase property, - IPriorityValueEntry entry, - Optional oldValue) + public void Completed(IPriorityValueEntry entry, Optional oldValue) { _entries.Remove((IPriorityValueEntry)entry); - - if (oldValue is Optional o) - { - UpdateEffectiveValue(new AvaloniaPropertyChangedEventArgs( - _owner, - Property, - o, - default, - entry.Priority)); - } + UpdateEffectiveValue(new AvaloniaPropertyChangedEventArgs( + _owner, + Property, + oldValue, + default, + entry.Priority)); } private int FindInsertPoint(BindingPriority priority) @@ -308,7 +307,7 @@ private void UpdateEffectiveValue(AvaloniaPropertyChangedEventArgs? change) var old = _value; _value = value; - _sink.ValueChanged(new AvaloniaPropertyChangedEventArgs( + _store.ValueChanged(new AvaloniaPropertyChangedEventArgs( _owner, Property, old, @@ -319,7 +318,7 @@ private void UpdateEffectiveValue(AvaloniaPropertyChangedEventArgs? change) { change.MarkNonEffectiveValue(); change.SetOldValue(default); - _sink.ValueChanged(change); + _store.ValueChanged(change); } } } diff --git a/src/Avalonia.Base/PropertyStore/ValueOwner.cs b/src/Avalonia.Base/PropertyStore/ValueOwner.cs new file mode 100644 index 00000000000..c68435f7a5d --- /dev/null +++ b/src/Avalonia.Base/PropertyStore/ValueOwner.cs @@ -0,0 +1,45 @@ +using Avalonia.Data; + +namespace Avalonia.PropertyStore +{ + /// + /// Represents a union type of and , + /// which are the valid owners of a value store . + /// + /// The value type. + internal readonly struct ValueOwner + { + private readonly ValueStore? _store; + private readonly PriorityValue? _priorityValue; + + public ValueOwner(ValueStore o) + { + _store = o; + _priorityValue = null; + } + + public ValueOwner(PriorityValue v) + { + _store = null; + _priorityValue = v; + } + + public bool IsValueStore => _store is not null; + + public void Completed(StyledPropertyBase property, IPriorityValueEntry entry, Optional oldValue) + { + if (_store is not null) + _store?.Completed(property, entry, oldValue); + else + _priorityValue!.Completed(entry, oldValue); + } + + public void ValueChanged(AvaloniaPropertyChangedEventArgs e) + { + if (_store is not null) + _store?.ValueChanged(e); + else + _priorityValue!.ValueChanged(e); + } + } +} diff --git a/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs b/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs index 238bb16e3eb..9f038214c4e 100644 --- a/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs +++ b/src/Avalonia.Base/Reactive/AvaloniaPropertyBindingObservable.cs @@ -51,7 +51,7 @@ private void PropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e is AvaloniaPropertyChangedEventArgs typedArgs) { - var newValue = e.Sender.GetValue(typedArgs.Property); + var newValue = e.Sender.GetValue(typedArgs.Property); if (!_value.HasValue || !EqualityComparer.Default.Equals(newValue, _value.Value)) { diff --git a/src/Avalonia.Base/Reactive/AvaloniaPropertyObservable.cs b/src/Avalonia.Base/Reactive/AvaloniaPropertyObservable.cs index fbc126bb059..cafce58c9ce 100644 --- a/src/Avalonia.Base/Reactive/AvaloniaPropertyObservable.cs +++ b/src/Avalonia.Base/Reactive/AvaloniaPropertyObservable.cs @@ -49,23 +49,31 @@ private void PropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e.Property == _property) { - T newValue; - - if (e is AvaloniaPropertyChangedEventArgs typed) + if (e.Sender is AvaloniaObject ao) { - newValue = typed.Sender.GetValue(typed.Property); + T newValue; + + if (e is AvaloniaPropertyChangedEventArgs typed) + { + newValue = AvaloniaObjectExtensions.GetValue(ao, typed.Property); + } + else + { + newValue = (T)e.Sender.GetValue(e.Property)!; + } + + if (!_value.HasValue || + !EqualityComparer.Default.Equals(newValue, _value.Value)) + { + _value = newValue; + PublishNext(_value.Value!); + } } else { - newValue = (T)e.Sender.GetValue(e.Property)!; + throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported."); } - if (!_value.HasValue || - !EqualityComparer.Default.Equals(newValue, _value.Value)) - { - _value = newValue; - PublishNext(_value.Value!); - } } } } diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs index 5f498623e15..f98d2cdbccb 100644 --- a/src/Avalonia.Base/StyledElement.cs +++ b/src/Avalonia.Base/StyledElement.cs @@ -467,7 +467,12 @@ void ISetLogicalParent.SetParent(ILogical? parent) /// The parent. void ISetInheritanceParent.SetParent(IAvaloniaObject? parent) { - InheritanceParent = parent; + InheritanceParent = parent switch + { + AvaloniaObject ao => ao, + null => null, + _ => throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.") + }; } void IStyleable.StyleApplied(IStyleInstance instance) diff --git a/src/Avalonia.Base/StyledPropertyBase.cs b/src/Avalonia.Base/StyledPropertyBase.cs index 535a826c1e2..f94723866a7 100644 --- a/src/Avalonia.Base/StyledPropertyBase.cs +++ b/src/Avalonia.Base/StyledPropertyBase.cs @@ -177,19 +177,19 @@ public override string ToString() object? IStyledPropertyAccessor.GetDefaultValue(Type type) => GetDefaultBoxedValue(type); /// - internal override void RouteClearValue(IAvaloniaObject o) + internal override void RouteClearValue(AvaloniaObject o) { o.ClearValue(this); } /// - internal override object? RouteGetValue(IAvaloniaObject o) + internal override object? RouteGetValue(AvaloniaObject o) { return o.GetValue(this); } /// - internal override object? RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority) + internal override object? RouteGetBaseValue(AvaloniaObject o, BindingPriority maxPriority) { var value = o.GetBaseValue(this, maxPriority); return value.HasValue ? value.Value : AvaloniaProperty.UnsetValue; @@ -197,7 +197,7 @@ internal override void RouteClearValue(IAvaloniaObject o) /// internal override IDisposable? RouteSetValue( - IAvaloniaObject o, + AvaloniaObject o, object? value, BindingPriority priority) { @@ -221,7 +221,7 @@ internal override void RouteClearValue(IAvaloniaObject o) /// internal override IDisposable RouteBind( - IAvaloniaObject o, + AvaloniaObject o, IObservable> source, BindingPriority priority) { @@ -232,7 +232,7 @@ internal override IDisposable RouteBind( /// internal override void RouteInheritanceParentChanged( AvaloniaObject o, - IAvaloniaObject? oldParent) + AvaloniaObject? oldParent) { o.InheritanceParentChanged(this, oldParent); } diff --git a/src/Avalonia.Base/ValueStore.cs b/src/Avalonia.Base/ValueStore.cs index 6b7b5980863..69c644dff9d 100644 --- a/src/Avalonia.Base/ValueStore.cs +++ b/src/Avalonia.Base/ValueStore.cs @@ -21,16 +21,15 @@ namespace Avalonia /// - For a single binding it will be an instance of /// - For all other cases it will be an instance of /// - internal class ValueStore : IValueSink + internal class ValueStore { private readonly AvaloniaObject _owner; - private readonly IValueSink _sink; private readonly AvaloniaPropertyValueStore _values; private BatchUpdate? _batchUpdate; public ValueStore(AvaloniaObject owner) { - _sink = _owner = owner; + _owner = owner; _values = new AvaloniaPropertyValueStore(); } @@ -122,7 +121,7 @@ public bool TryGetValue( } else { - var entry = new ConstantValueEntry(property, value, priority, this); + var entry = new ConstantValueEntry(property, value, priority, new(this)); AddValue(property, entry); NotifyValueChanged(property, default, value, priority); result = entry; @@ -151,7 +150,7 @@ public IDisposable AddBinding( } else { - var entry = new BindingEntry(_owner, property, source, priority, this); + var entry = new BindingEntry(_owner, property, source, priority, new(this)); AddValue(property, entry); return entry; } @@ -187,7 +186,7 @@ public void ClearLocalValue(StyledPropertyBase property) // so there's no way to mark them for removal at the end of a batch update. Instead convert // them to a constant value entry with Unset priority in the event of a local value being // cleared during a batch update. - var sentinel = new ConstantValueEntry(property, Optional.Empty, BindingPriority.Unset, _sink); + var sentinel = new ConstantValueEntry(property, Optional.Empty, BindingPriority.Unset, new(this)); _values.SetValue(property, sentinel); } @@ -196,11 +195,11 @@ public void ClearLocalValue(StyledPropertyBase property) } } - public void CoerceValue(StyledPropertyBase property) + public void CoerceValue(AvaloniaProperty property) { if (TryGetValue(property, out var slot)) { - if (slot is PriorityValue p) + if (slot is IPriorityValue p) { p.UpdateEffectiveValue(); } @@ -222,7 +221,7 @@ public void CoerceValue(StyledPropertyBase property) return null; } - void IValueSink.ValueChanged(AvaloniaPropertyChangedEventArgs change) + public void ValueChanged(AvaloniaPropertyChangedEventArgs change) { if (_batchUpdate is object) { @@ -233,11 +232,11 @@ void IValueSink.ValueChanged(AvaloniaPropertyChangedEventArgs change) } else { - _sink.ValueChanged(change); + _owner.ValueChanged(change); } } - void IValueSink.Completed( + public void Completed( StyledPropertyBase property, IPriorityValueEntry entry, Optional oldValue) @@ -248,7 +247,7 @@ void IValueSink.Completed( if (_batchUpdate is null) { _values.Remove(property); - _sink.Completed(property, entry, oldValue); + _owner.Completed(property, entry, oldValue); } else { @@ -352,7 +351,7 @@ private void NotifyValueChanged( { if (_batchUpdate is null) { - _sink.ValueChanged(new AvaloniaPropertyChangedEventArgs( + _owner.ValueChanged(new AvaloniaPropertyChangedEventArgs( _owner, property, oldValue, @@ -451,7 +450,7 @@ public bool End() }; // Call _sink.ValueChanged with an appropriately typed AvaloniaPropertyChangedEventArgs. - slot.RaiseValueChanged(_owner._sink, _owner._owner, entry.property, oldValue, newValue); + slot.RaiseValueChanged(_owner._owner, entry.property, oldValue, newValue); // During batch update values can't be removed immediately because they're needed to raise // the _sink.ValueChanged notification. They instead mark themselves for removal by setting diff --git a/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt b/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt index fcc74cf8643..bfcec2960a1 100644 --- a/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt +++ b/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt @@ -1 +1,4 @@ -Total Issues: 0 +Compat issues with assembly Avalonia.Controls.DataGrid: +MembersMustExist : Member 'protected void Avalonia.Controls.DataGridCheckBoxColumn.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.DataGridTextColumn.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +Total Issues: 2 diff --git a/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs index ccf1f3f77a5..9826c15598a 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs @@ -46,7 +46,7 @@ public bool IsThreeState set => SetValue(IsThreeStateProperty, value); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs index 4a7137dcda2..f3ea48ff80d 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs @@ -192,14 +192,14 @@ public bool IsVisible set => SetValue(IsVisibleProperty, value); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == IsVisibleProperty) { OwningGrid?.OnColumnVisibleStateChanging(this); - var isVisible = change.NewValue.GetValueOrDefault(); + var isVisible = change.GetNewValue(); if (_headerCell != null) { diff --git a/src/Avalonia.Controls.DataGrid/DataGridRow.cs b/src/Avalonia.Controls.DataGrid/DataGridRow.cs index db5d4289424..b062a14e39c 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridRow.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridRow.cs @@ -1062,7 +1062,7 @@ internal void ApplyDetailsTemplate(bool initializeDetailsPreferredHeight) } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Property == DataContextProperty) { diff --git a/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs index 68736dee7f4..bb8637cda27 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs @@ -119,7 +119,7 @@ public IBrush Foreground set => SetValue(ForegroundProperty, value); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt index fe3ac317340..33e5efbc151 100644 --- a/src/Avalonia.Controls/ApiCompatBaseline.txt +++ b/src/Avalonia.Controls/ApiCompatBaseline.txt @@ -1,11 +1,17 @@ Compat issues with assembly Avalonia.Controls: +MembersMustExist : Member 'protected void Avalonia.Controls.Button.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.ButtonSpinner.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.CalendarDatePicker.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.ContextMenu.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. TypesMustExist : Type 'Avalonia.Controls.DropDown' does not exist in the implementation but it does exist in the contract. TypesMustExist : Type 'Avalonia.Controls.DropDownItem' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Expander.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.IMenuItem.StaysOpenOnClick' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.IMenuItem.StaysOpenOnClick.get()' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.ItemsRepeater.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.DirectProperty Avalonia.DirectProperty Avalonia.Controls.NumericUpDown.ValueProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.NumericUpDown.IncrementProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.NumericUpDown.MaximumProperty' does not exist in the implementation but it does exist in the contract. @@ -30,7 +36,9 @@ MembersMustExist : Member 'public void Avalonia.Controls.NumericUpDown.Value.set MembersMustExist : Member 'public void Avalonia.Controls.NumericUpDownValueChangedEventArgs..ctor(Avalonia.Interactivity.RoutedEvent, System.Double, System.Double)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public System.Double Avalonia.Controls.NumericUpDownValueChangedEventArgs.NewValue.get()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public System.Double Avalonia.Controls.NumericUpDownValueChangedEventArgs.OldValue.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.ProgressBar.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.ScrollViewer.AllowAutoHideProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Slider.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.AttachedProperty Avalonia.AttachedProperty Avalonia.Controls.TextBlock.FontFamilyProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.AttachedProperty Avalonia.AttachedProperty Avalonia.Controls.TextBlock.FontStyleProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.AttachedProperty Avalonia.AttachedProperty Avalonia.Controls.TextBlock.FontWeightProperty' does not exist in the implementation but it does exist in the contract. @@ -51,10 +59,12 @@ MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetFontSize(A MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetFontStyle(Avalonia.Controls.Control, Avalonia.Media.FontStyle)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetFontWeight(Avalonia.Controls.Control, Avalonia.Media.FontWeight)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetForeground(Avalonia.Controls.Control, Avalonia.Media.IBrush)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.TextBox.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.TopLevel' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Viewbox' does not inherit from base type 'Avalonia.Controls.Decorator' in the implementation but it does in the contract. MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Viewbox.StretchProperty' does not exist in the implementation but it does exist in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Window' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Window.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.WindowBase' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. InterfacesShouldHaveSameMembers : Interface member 'public System.EventHandler Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.ShutdownRequested' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.add_ShutdownRequested(System.EventHandler)' is present in the implementation but not in the contract. @@ -65,12 +75,17 @@ MembersMustExist : Member 'public System.Action Avalonia.Controls MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.set(System.Action)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Notifications.WindowNotificationManager.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.Platform.ITopLevelNativeMenuExporter.SetNativeMenu(Avalonia.Controls.NativeMenu)' is present in the contract but not in the implementation. +MembersMustExist : Member 'protected void Avalonia.Controls.Presenters.ScrollContentPresenter.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'protected Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.CreateFormattedText()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.FormattedText.get()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public System.Int32 Avalonia.Controls.Presenters.TextPresenter.GetCaretIndex(Avalonia.Point)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'protected void Avalonia.Controls.Presenters.TextPresenter.InvalidateFormattedText()' does not exist in the implementation but it does exist in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Primitives.PopupRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.ScrollBar.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.SelectingItemsControl.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.Track.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract. TypesMustExist : Type 'Avalonia.Platform.ExportWindowingSubsystemAttribute' does not exist in the implementation but it does exist in the contract. EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.Screen Avalonia.Platform.IScreenImpl.ScreenFromPoint(Avalonia.PixelPoint)' is present in the implementation but not in the contract. @@ -94,4 +109,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract. -Total Issues: 95 +Total Issues: 110 diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index a4d15bab8d3..a4a147e0f32 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -413,7 +413,7 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) } /// - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -421,12 +421,13 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs { if (((ILogical)this).IsAttachedToLogicalTree) { - if (change.OldValue.GetValueOrDefault() is ICommand oldCommand) + var (oldValue, newValue) = change.GetOldAndNewValue(); + if (oldValue is ICommand oldCommand) { oldCommand.CanExecuteChanged -= CanExecuteChanged; } - if (change.NewValue.GetValueOrDefault() is ICommand newCommand) + if (newValue is ICommand newCommand) { newCommand.CanExecuteChanged += CanExecuteChanged; } @@ -440,7 +441,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == IsCancelProperty) { - var isCancel = change.NewValue.GetValueOrDefault(); + var isCancel = change.GetNewValue(); if (VisualRoot is IInputElement inputRoot) { @@ -456,7 +457,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == IsDefaultProperty) { - var isDefault = change.NewValue.GetValueOrDefault(); + var isDefault = change.GetNewValue(); if (VisualRoot is IInputElement inputRoot) { @@ -476,8 +477,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == FlyoutProperty) { - var oldFlyout = change.OldValue.GetValueOrDefault() as FlyoutBase; - var newFlyout = change.NewValue.GetValueOrDefault() as FlyoutBase; + var (oldFlyout, newFlyout) = change.GetOldAndNewValue(); // If flyout is changed while one is already open, make sure we // close the old one first diff --git a/src/Avalonia.Controls/ButtonSpinner.cs b/src/Avalonia.Controls/ButtonSpinner.cs index 29a954098fc..e455c6c6f32 100644 --- a/src/Avalonia.Controls/ButtonSpinner.cs +++ b/src/Avalonia.Controls/ButtonSpinner.cs @@ -210,13 +210,13 @@ protected override void OnPointerWheelChanged(PointerWheelEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == ButtonSpinnerLocationProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index bc5195ff6c8..ee2378101af 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -241,13 +241,13 @@ private static void ContextMenuChanged(AvaloniaPropertyChangedEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == WindowManagerAddShadowHintProperty && _popup != null) { - _popup.WindowManagerAddShadowHint = change.NewValue.GetValueOrDefault(); + _popup.WindowManagerAddShadowHint = change.GetNewValue(); } } diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index 2c696c8f746..d6a5fa07272 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -348,7 +348,7 @@ protected override void OnKeyUp(KeyEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/Documents/Inline.cs b/src/Avalonia.Controls/Documents/Inline.cs index 5b63f954329..fdd78459c8c 100644 --- a/src/Avalonia.Controls/Documents/Inline.cs +++ b/src/Avalonia.Controls/Documents/Inline.cs @@ -55,7 +55,7 @@ protected TextRunProperties CreateTextRunProperties() TextDecorations, Foreground, Background, BaselineAlignment); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/Documents/Run.cs b/src/Avalonia.Controls/Documents/Run.cs index a7dd5fd94f9..2f9ba013edf 100644 --- a/src/Avalonia.Controls/Documents/Run.cs +++ b/src/Avalonia.Controls/Documents/Run.cs @@ -71,7 +71,7 @@ internal override int AppendText(StringBuilder stringBuilder) return text.Length; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/Documents/TextElement.cs b/src/Avalonia.Controls/Documents/TextElement.cs index d8e13554b52..450aafbfaf6 100644 --- a/src/Avalonia.Controls/Documents/TextElement.cs +++ b/src/Avalonia.Controls/Documents/TextElement.cs @@ -256,7 +256,7 @@ public static void SetForeground(Control control, IBrush? value) /// public event EventHandler? Invalidated; - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs index 020b1628640..3ba99d8a67a 100644 --- a/src/Avalonia.Controls/Expander.cs +++ b/src/Avalonia.Controls/Expander.cs @@ -106,13 +106,13 @@ protected virtual async void OnIsExpandedChanged(AvaloniaPropertyChangedEventArg } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == ExpandDirectionProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index ab236f703d2..256160a116d 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -341,13 +341,13 @@ protected override AutomationPeer OnCreateAutomationPeer() return new ItemsControlAutomationPeer(this); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == ItemCountProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/MaskedTextBox.cs b/src/Avalonia.Controls/MaskedTextBox.cs index ad64c61ebef..933788f9ea9 100644 --- a/src/Avalonia.Controls/MaskedTextBox.cs +++ b/src/Avalonia.Controls/MaskedTextBox.cs @@ -280,7 +280,7 @@ protected override void OnLostFocus(RoutedEventArgs e) base.OnLostFocus(e); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { void UpdateMaskProvider() { diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs index d6b82a8f8af..2449f4c15c3 100644 --- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs +++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs @@ -139,13 +139,13 @@ public async void Show(object content) notificationControl.Close(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == PositionProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 8229f25a078..03159c7a8ed 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -403,7 +403,7 @@ public sealed override void ApplyTemplate() } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); switch (change.Property.Name) diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs index a8bffcc8428..c526b7ac49f 100644 --- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs @@ -469,7 +469,7 @@ protected override void OnPointerWheelChanged(PointerWheelEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Property == OffsetProperty && !_arranging) { diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 7f2dde7c1ed..d127866640c 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -776,7 +776,7 @@ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e _caretTimer.Tick -= CaretTimerTick; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs index 353f12118f5..fb047d93dfb 100644 --- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs +++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs @@ -69,15 +69,18 @@ protected override Size MeasureOverride(Size availableSize) { foreach (var child in Children) { - var info = child.GetValue(s_adornedElementInfoProperty); - - if (info != null && info.Bounds.HasValue) - { - child.Measure(info.Bounds.Value.Bounds.Size); - } - else + if (child is AvaloniaObject ao) { - child.Measure(availableSize); + var info = ao.GetValue(s_adornedElementInfoProperty); + + if (info != null && info.Bounds.HasValue) + { + child.Measure(info.Bounds.Value.Bounds.Size); + } + else + { + child.Measure(availableSize); + } } } @@ -88,19 +91,22 @@ protected override Size ArrangeOverride(Size finalSize) { foreach (var child in Children) { - var info = child.GetValue(s_adornedElementInfoProperty); - var isClipEnabled = child.GetValue(IsClipEnabledProperty); - - if (info != null && info.Bounds.HasValue) - { - child.RenderTransform = new MatrixTransform(info.Bounds.Value.Transform); - child.RenderTransformOrigin = new RelativePoint(new Point(0,0), RelativeUnit.Absolute); - UpdateClip(child, info.Bounds.Value, isClipEnabled); - child.Arrange(info.Bounds.Value.Bounds); - } - else + if (child is AvaloniaObject ao) { - child.Arrange(new Rect(finalSize)); + var info = ao.GetValue(s_adornedElementInfoProperty); + var isClipEnabled = ao.GetValue(IsClipEnabledProperty); + + if (info != null && info.Bounds.HasValue) + { + child.RenderTransform = new MatrixTransform(info.Bounds.Value.Transform); + child.RenderTransformOrigin = new RelativePoint(new Point(0, 0), RelativeUnit.Absolute); + UpdateClip(child, info.Bounds.Value, isClipEnabled); + child.Arrange(info.Bounds.Value.Bounds); + } + else + { + child.Arrange(new Rect(finalSize)); + } } } diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs index 6a30097fbb5..e5c3392faf1 100644 --- a/src/Avalonia.Controls/Primitives/ScrollBar.cs +++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs @@ -194,13 +194,13 @@ protected override void OnKeyDown(KeyEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == OrientationProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } else if (change.Property == AllowAutoHideProperty) { diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index cec02c7ae9e..6f2554bef37 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -533,9 +533,9 @@ protected override void OnTextInput(TextInputEventArgs e) bool Match(ItemContainerInfo info) { - if (info.ContainerControl.IsSet(TextSearch.TextProperty)) + if (info.ContainerControl is AvaloniaObject ao && ao.IsSet(TextSearch.TextProperty)) { - var searchText = info.ContainerControl.GetValue(TextSearch.TextProperty); + var searchText = ao.GetValue(TextSearch.TextProperty); if (searchText?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true) { @@ -585,7 +585,7 @@ protected override void OnKeyDown(KeyEventArgs e) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -595,7 +595,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } if (change.Property == ItemsProperty && _updateState is null && _selection is object) { - var newValue = change.NewValue.GetValueOrDefault(); + var newValue = change.GetNewValue(); _selection.Source = newValue; if (newValue is null) @@ -605,7 +605,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == SelectionModeProperty && _selection is object) { - var newValue = change.NewValue.GetValueOrDefault(); + var newValue = change.GetNewValue(); _selection.SingleSelect = !newValue.HasAllFlags(SelectionMode.Multiple); } else if (change.Property == WrapSelectionProperty) diff --git a/src/Avalonia.Controls/Primitives/Track.cs b/src/Avalonia.Controls/Primitives/Track.cs index f8d60461011..49f0cda982c 100644 --- a/src/Avalonia.Controls/Primitives/Track.cs +++ b/src/Avalonia.Controls/Primitives/Track.cs @@ -291,13 +291,13 @@ protected override Size ArrangeOverride(Size arrangeSize) return arrangeSize; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == OrientationProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs index a4f2cc799a2..1075328c67b 100644 --- a/src/Avalonia.Controls/ProgressBar.cs +++ b/src/Avalonia.Controls/ProgressBar.cs @@ -178,17 +178,17 @@ protected override Size ArrangeOverride(Size finalSize) return base.ArrangeOverride(finalSize); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == IsIndeterminateProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault(), null); + UpdatePseudoClasses(change.GetNewValue(), null); } else if (change.Property == OrientationProperty) { - UpdatePseudoClasses(null, change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(null, change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/RepeatButton.cs b/src/Avalonia.Controls/RepeatButton.cs index 0415a787216..80f841fa185 100644 --- a/src/Avalonia.Controls/RepeatButton.cs +++ b/src/Avalonia.Controls/RepeatButton.cs @@ -70,11 +70,11 @@ private void StopTimer() _repeatTimer?.Stop(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); - if (change.Property == IsPressedProperty && change.NewValue.GetValueOrDefault() == false) + if (change.Property == IsPressedProperty && change.GetNewValue() == false) { StopTimer(); } diff --git a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs index 6811fd74727..3f42d95debf 100644 --- a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs +++ b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs @@ -267,10 +267,9 @@ bool IChildIndexProvider.TryGetTotalCount(out int count) internal void UnpinElement(IControl element) => _viewManager.UpdatePin(element, false); - internal static VirtualizationInfo TryGetVirtualizationInfo(IControl element) + internal static VirtualizationInfo? TryGetVirtualizationInfo(IControl element) { - var value = element.GetValue(VirtualizationInfoProperty); - return value; + return (element as AvaloniaObject)?.GetValue(VirtualizationInfoProperty); } internal static VirtualizationInfo CreateAndInitializeVirtualizationInfo(IControl element) @@ -287,15 +286,20 @@ internal static VirtualizationInfo CreateAndInitializeVirtualizationInfo(IContro internal static VirtualizationInfo GetVirtualizationInfo(IControl element) { - var result = element.GetValue(VirtualizationInfoProperty); - - if (result == null) + if (element is AvaloniaObject ao) { - result = new VirtualizationInfo(); - element.SetValue(VirtualizationInfoProperty, result); + var result = ao.GetValue(VirtualizationInfoProperty); + + if (result == null) + { + result = new VirtualizationInfo(); + ao.SetValue(VirtualizationInfoProperty, result); + } + + return result; } - return result; + throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported."); } private protected override void InvalidateMeasureOnChildrenChanged() @@ -426,12 +430,11 @@ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e _viewportManager.ResetScrollers(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (change.Property == ItemsProperty) { - var oldEnumerable = change.OldValue.GetValueOrDefault(); - var newEnumerable = change.NewValue.GetValueOrDefault(); + var (oldEnumerable, newEnumerable) = change.GetOldAndNewValue(); if (oldEnumerable != newEnumerable) { @@ -446,23 +449,21 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == ItemTemplateProperty) { - OnItemTemplateChanged( - change.OldValue.GetValueOrDefault(), - change.NewValue.GetValueOrDefault()); + var (oldvalue, newValue) = change.GetOldAndNewValue(); + OnItemTemplateChanged(oldvalue, newValue); } else if (change.Property == LayoutProperty) { - OnLayoutChanged( - change.OldValue.GetValueOrDefault(), - change.NewValue.GetValueOrDefault()); + var (oldvalue, newValue) = change.GetOldAndNewValue(); + OnLayoutChanged(oldvalue, newValue); } else if (change.Property == HorizontalCacheLengthProperty) { - _viewportManager.HorizontalCacheLength = change.NewValue.GetValueOrDefault(); + _viewportManager.HorizontalCacheLength = change.GetNewValue(); } else if (change.Property == VerticalCacheLengthProperty) { - _viewportManager.VerticalCacheLength = change.NewValue.GetValueOrDefault(); + _viewportManager.VerticalCacheLength = change.GetNewValue(); } base.OnPropertyChanged(change); @@ -497,7 +498,7 @@ private int GetElementIndexImpl(IControl element) if (parent == this) { var virtInfo = TryGetVirtualizationInfo(element); - return _viewManager.GetElementIndex(virtInfo); + return _viewManager.GetElementIndex(virtInfo!); } return -1; diff --git a/src/Avalonia.Controls/Repeater/RecyclePool.cs b/src/Avalonia.Controls/Repeater/RecyclePool.cs index 9e2da81f991..cf2b40836ed 100644 --- a/src/Avalonia.Controls/Repeater/RecyclePool.cs +++ b/src/Avalonia.Controls/Repeater/RecyclePool.cs @@ -80,8 +80,8 @@ public void PutElement(IControl element, string key, IControl? owner) return null; } - internal string GetReuseKey(IControl element) => element.GetValue(ReuseKeyProperty); - internal void SetReuseKey(IControl element, string value) => element.SetValue(ReuseKeyProperty, value); + internal string GetReuseKey(IControl element) => ((Control)element).GetValue(ReuseKeyProperty); + internal void SetReuseKey(IControl element, string value) => ((Control)element).SetValue(ReuseKeyProperty, value); private IPanel? EnsureOwnerIsPanelOrNull(IControl? owner) { diff --git a/src/Avalonia.Controls/Repeater/ViewManager.cs b/src/Avalonia.Controls/Repeater/ViewManager.cs index b28753b5189..12db48a2c25 100644 --- a/src/Avalonia.Controls/Repeater/ViewManager.cs +++ b/src/Avalonia.Controls/Repeater/ViewManager.cs @@ -47,7 +47,7 @@ public IControl GetElement(int index, bool forceCreate, bool suppressAutoRecycle if (madeAnchor != null) { var anchorVirtInfo = ItemsRepeater.TryGetVirtualizationInfo(madeAnchor); - if (anchorVirtInfo.Index == index) + if (anchorVirtInfo!.Index == index) { element = madeAnchor; } @@ -60,12 +60,12 @@ public IControl GetElement(int index, bool forceCreate, bool suppressAutoRecycle var virtInfo = ItemsRepeater.TryGetVirtualizationInfo(element); if (suppressAutoRecycle) { - virtInfo.AutoRecycleCandidate = false; + virtInfo!.AutoRecycleCandidate = false; Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "GetElement: {Index} Not AutoRecycleCandidate:", virtInfo.Index); } else { - virtInfo.AutoRecycleCandidate = true; + virtInfo!.AutoRecycleCandidate = true; virtInfo.KeepAlive = true; Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "GetElement: {Index} AutoRecycleCandidate:", virtInfo.Index); } diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs index f2bd1947d64..f0a0fba1af2 100644 --- a/src/Avalonia.Controls/Slider.cs +++ b/src/Avalonia.Controls/Slider.cs @@ -369,13 +369,13 @@ protected override void UpdateDataValidation(AvaloniaProperty property, Bi } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == OrientationProperty) { - UpdatePseudoClasses(change.NewValue.GetValueOrDefault()); + UpdatePseudoClasses(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/SplitButton/SplitButton.cs b/src/Avalonia.Controls/SplitButton/SplitButton.cs index f2f4e951aef..37cdefd4e56 100644 --- a/src/Avalonia.Controls/SplitButton/SplitButton.cs +++ b/src/Avalonia.Controls/SplitButton/SplitButton.cs @@ -276,19 +276,21 @@ protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs } /// - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) { if (e.Property == CommandProperty) { if (_isAttachedToLogicalTree) { // Must unregister events here while a reference to the old command still exists - if (e.OldValue.GetValueOrDefault() is ICommand oldCommand) + var (oldValue, newValue) = e.GetOldAndNewValue(); + + if (oldValue is ICommand oldCommand) { oldCommand.CanExecuteChanged -= CanExecuteChanged; } - if (e.NewValue.GetValueOrDefault() is ICommand newCommand) + if (newValue is ICommand newCommand) { newCommand.CanExecuteChanged += CanExecuteChanged; } @@ -302,8 +304,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (e.Property == FlyoutProperty) { - var oldFlyout = e.OldValue.GetValueOrDefault() as FlyoutBase; - var newFlyout = e.NewValue.GetValueOrDefault() as FlyoutBase; + var (oldFlyout, newFlyout) = e.GetOldAndNewValue(); // If flyout is changed while one is already open, make sure we // close the old one first diff --git a/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs b/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs index 879c1aa6e1c..cd34f8060ab 100644 --- a/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs +++ b/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs @@ -90,7 +90,7 @@ protected void Toggle() //////////////////////////////////////////////////////////////////////// /// - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) { if (e.Property == IsCheckedProperty) { diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 36e5f7236f0..3b8842fa0ed 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -639,7 +639,7 @@ protected override AutomationPeer OnCreateAutomationPeer() private static bool IsValidLineHeight(double lineHeight) => double.IsNaN(lineHeight) || lineHeight > 0; - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 947830b217d..1f3dbc87db8 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -585,7 +585,7 @@ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e _imClient.SetPresenter(null, null); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -594,7 +594,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs UpdatePseudoclasses(); UpdateCommandStates(); } - else if (change.Property == IsUndoEnabledProperty && change.NewValue.GetValueOrDefault() == false) + else if (change.Property == IsUndoEnabledProperty && change.GetNewValue() == false) { // from docs at // https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.isundoenabled: diff --git a/src/Avalonia.Controls/TransitioningContentControl.cs b/src/Avalonia.Controls/TransitioningContentControl.cs index cb0d2291108..451e234653c 100644 --- a/src/Avalonia.Controls/TransitioningContentControl.cs +++ b/src/Avalonia.Controls/TransitioningContentControl.cs @@ -61,7 +61,7 @@ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e _lastTransitionCts?.Cancel(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/src/Avalonia.Controls/TrayIcon.cs b/src/Avalonia.Controls/TrayIcon.cs index b8ab48a2b71..2ccb03e4473 100644 --- a/src/Avalonia.Controls/TrayIcon.cs +++ b/src/Avalonia.Controls/TrayIcon.cs @@ -206,7 +206,7 @@ private static void RemoveIcons(IEnumerable icons) } } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -216,15 +216,15 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs } else if (change.Property == IsVisibleProperty) { - _impl?.SetIsVisible(change.NewValue.GetValueOrDefault()); + _impl?.SetIsVisible(change.GetNewValue()); } else if (change.Property == ToolTipTextProperty) { - _impl?.SetToolTipText(change.NewValue.GetValueOrDefault()); + _impl?.SetToolTipText(change.GetNewValue()); } else if (change.Property == MenuProperty) { - _impl?.MenuExporter?.SetNativeMenu(change.NewValue.GetValueOrDefault()); + _impl?.MenuExporter?.SetNativeMenu(change.GetNewValue()); } } diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs index 50b9560cace..dd74d549bdd 100644 --- a/src/Avalonia.Controls/Viewbox.cs +++ b/src/Avalonia.Controls/Viewbox.cs @@ -82,13 +82,13 @@ protected internal ITransform? InternalTransform set => _containerVisual.RenderTransform = value; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == ChildProperty) { - _containerVisual.Child = change.NewValue.GetValueOrDefault(); + _containerVisual.Child = change.GetNewValue(); InvalidateMeasure(); } } diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 993b3aaa1b3..a5f99918b2e 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -1019,16 +1019,16 @@ protected sealed override void HandleResized(Size clientSize, PlatformResizeReas /// protected virtual void OnClosing(CancelEventArgs e) => Closing?.Invoke(this, e); - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == SystemDecorationsProperty) { - var typedNewValue = change.NewValue.GetValueOrDefault(); + var (typedOldValue, typedNewValue) = change.GetOldAndNewValue(); PlatformImpl?.SetSystemDecorations(typedNewValue); - var o = change.OldValue.GetValueOrDefault() == SystemDecorations.Full; + var o = typedOldValue == SystemDecorations.Full; var n = typedNewValue == SystemDecorations.Full; if (o != n) diff --git a/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs index cb98fb70f30..ec7e91c8bea 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs @@ -92,7 +92,7 @@ public IBrush Highlight set => SetValue(HighlightProperty, value); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -102,7 +102,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs { _isUpdatingThickness = true; - var value = change.NewValue.GetValueOrDefault(); + var value = change.GetNewValue(); Left = value.Left; Top = value.Top; diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs index 4dc0c34c0a5..0c0c005122a 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs @@ -110,7 +110,7 @@ public VerticalAlignment VerticalAlignment private void UpdateSizeConstraints() { - if (_control is IAvaloniaObject ao) + if (_control is AvaloniaObject ao) { string? CreateConstraintInfo(StyledProperty minProperty, StyledProperty maxProperty) { @@ -191,7 +191,7 @@ public void ControlPropertyChanged(object? sender, AvaloniaPropertyChangedEventA } else { - if (_control is IAvaloniaObject ao) + if (_control is AvaloniaObject ao) { if (e.Property == Layoutable.MarginProperty) { diff --git a/src/Avalonia.Themes.Default/SimpleTheme.cs b/src/Avalonia.Themes.Default/SimpleTheme.cs index 1d9f2d5f9d4..69296607578 100644 --- a/src/Avalonia.Themes.Default/SimpleTheme.cs +++ b/src/Avalonia.Themes.Default/SimpleTheme.cs @@ -116,7 +116,7 @@ public bool TryGetResource(object key, out object? value) return false; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == ModeProperty) diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.cs b/src/Avalonia.Themes.Fluent/FluentTheme.cs index d1136d44a49..f6b47a54668 100644 --- a/src/Avalonia.Themes.Fluent/FluentTheme.cs +++ b/src/Avalonia.Themes.Fluent/FluentTheme.cs @@ -78,7 +78,7 @@ public DensityStyle DensityStyle set => SetValue(DensityStyleProperty, value); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == ModeProperty) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs index 76f3cc071fa..5da40035d2c 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -138,7 +138,7 @@ public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) NameScopeSetNameScope = NameScope.GetMethod(new FindMethodMethodSignature("SetNameScope", XamlIlTypes.Void, StyledElement, INameScope) { IsStatic = true }); - AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void, + AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", IDisposable, false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority); IPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.IPropertyInfo"); ClrPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.ClrPropertyInfo"); diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs index e8fc3f9f409..7f4dcace719 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs @@ -109,25 +109,26 @@ public Class1() public List Changes { get; } public List CoreChanges { get; } - protected override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) { CoreChanges.Add(Clone(change)); base.OnPropertyChangedCore(change); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { Changes.Add(Clone(change)); base.OnPropertyChanged(change); } - private static AvaloniaPropertyChangedEventArgs Clone(AvaloniaPropertyChangedEventArgs change) + private static AvaloniaPropertyChangedEventArgs Clone(AvaloniaPropertyChangedEventArgs change) { - var result = new AvaloniaPropertyChangedEventArgs( + var e = (AvaloniaPropertyChangedEventArgs)change; + var result = new AvaloniaPropertyChangedEventArgs( change.Sender, - change.Property, - change.OldValue, - change.NewValue, + e.Property, + e.OldValue, + e.NewValue, change.Priority); if (!change.IsEffectiveValueChange) diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs index 1adb6988a28..ee29c823458 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs @@ -152,35 +152,35 @@ public override void Accept(IAvaloniaPropertyVisitor vistor, ref T } internal override IDisposable RouteBind( - IAvaloniaObject o, + AvaloniaObject o, IObservable> source, BindingPriority priority) { throw new NotImplementedException(); } - internal override void RouteClearValue(IAvaloniaObject o) + internal override void RouteClearValue(AvaloniaObject o) { throw new NotImplementedException(); } - internal override object RouteGetValue(IAvaloniaObject o) + internal override object RouteGetValue(AvaloniaObject o) { throw new NotImplementedException(); } - internal override object RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority) + internal override object RouteGetBaseValue(AvaloniaObject o, BindingPriority maxPriority) { throw new NotImplementedException(); } - internal override void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject oldParent) + internal override void RouteInheritanceParentChanged(AvaloniaObject o, AvaloniaObject oldParent) { throw new NotImplementedException(); } internal override IDisposable RouteSetValue( - IAvaloniaObject o, + AvaloniaObject o, object value, BindingPriority priority) { diff --git a/tests/Avalonia.Base.UnitTests/PriorityValueTests.cs b/tests/Avalonia.Base.UnitTests/PriorityValueTests.cs index 0caa984a22f..aa5993f3b22 100644 --- a/tests/Avalonia.Base.UnitTests/PriorityValueTests.cs +++ b/tests/Avalonia.Base.UnitTests/PriorityValueTests.cs @@ -10,8 +10,8 @@ namespace Avalonia.Base.UnitTests { public class PriorityValueTests { - private static readonly IValueSink NullSink = new MockSink(); - private static readonly IAvaloniaObject Owner = Mock.Of(); + private static readonly AvaloniaObject Owner = new AvaloniaObject(); + private static readonly ValueStore ValueStore = new ValueStore(Owner); private static readonly StyledProperty TestProperty = new StyledProperty( "Test", typeof(PriorityValueTests), @@ -23,12 +23,12 @@ public void Constructor_Should_Set_Value_Based_On_Initial_Entry() var target = new PriorityValue( Owner, TestProperty, - NullSink, + ValueStore, new ConstantValueEntry( TestProperty, "1", BindingPriority.StyleTrigger, - NullSink)); + new(ValueStore))); Assert.Equal("1", target.GetValue().Value); Assert.Equal(BindingPriority.StyleTrigger, target.Priority); @@ -40,7 +40,7 @@ public void GetValue_Should_Respect_MaxPriority() var target = new PriorityValue( Owner, TestProperty, - NullSink); + ValueStore); target.SetValue("animation", BindingPriority.Animation); target.SetValue("local", BindingPriority.LocalValue); @@ -60,7 +60,7 @@ public void SetValue_LocalValue_Should_Not_Add_Entries() var target = new PriorityValue( Owner, TestProperty, - NullSink); + ValueStore); target.SetValue("1", BindingPriority.LocalValue); target.SetValue("2", BindingPriority.LocalValue); @@ -74,7 +74,7 @@ public void SetValue_Non_LocalValue_Should_Add_Entries() var target = new PriorityValue( Owner, TestProperty, - NullSink); + ValueStore); target.SetValue("1", BindingPriority.Style); target.SetValue("2", BindingPriority.Animation); @@ -93,7 +93,7 @@ public void Priority_Should_Be_Set() var target = new PriorityValue( Owner, TestProperty, - NullSink); + ValueStore); Assert.Equal(BindingPriority.Unset, target.Priority); target.SetValue("style", BindingPriority.Style); @@ -109,7 +109,7 @@ public void Priority_Should_Be_Set() [Fact] public void Binding_With_Same_Priority_Should_Be_Appended() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); @@ -129,7 +129,7 @@ public void Binding_With_Same_Priority_Should_Be_Appended() [Fact] public void Binding_With_Higher_Priority_Should_Be_Appended() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); @@ -149,7 +149,7 @@ public void Binding_With_Higher_Priority_Should_Be_Appended() [Fact] public void Binding_With_Lower_Priority_Should_Be_Prepended() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); @@ -169,7 +169,7 @@ public void Binding_With_Lower_Priority_Should_Be_Prepended() [Fact] public void Second_Binding_With_Lower_Priority_Should_Be_Inserted_In_Middle() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); var source3 = new Source("3"); @@ -191,7 +191,7 @@ public void Second_Binding_With_Lower_Priority_Should_Be_Inserted_In_Middle() [Fact] public void Competed_Binding_Should_Be_Removed() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); var source3 = new Source("3"); @@ -214,7 +214,7 @@ public void Competed_Binding_Should_Be_Removed() [Fact] public void Value_Should_Come_From_Last_Entry() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); var source3 = new Source("3"); @@ -229,7 +229,7 @@ public void Value_Should_Come_From_Last_Entry() [Fact] public void LocalValue_Should_Override_LocalValue_Binding() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); target.AddBinding(source1, BindingPriority.LocalValue).Start(); @@ -241,7 +241,7 @@ public void LocalValue_Should_Override_LocalValue_Binding() [Fact] public void LocalValue_Should_Override_Style_Binding() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); target.AddBinding(source1, BindingPriority.Style).Start(); @@ -253,7 +253,7 @@ public void LocalValue_Should_Override_Style_Binding() [Fact] public void LocalValue_Should_Not_Override_Animation_Binding() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); target.AddBinding(source1, BindingPriority.Animation).Start(); @@ -265,7 +265,7 @@ public void LocalValue_Should_Not_Override_Animation_Binding() [Fact] public void NonAnimated_Value_Should_Be_Correct_1() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); var source3 = new Source("3"); @@ -281,7 +281,7 @@ public void NonAnimated_Value_Should_Be_Correct_1() [Fact] public void NonAnimated_Value_Should_Be_Correct_2() { - var target = new PriorityValue(Owner, TestProperty, NullSink); + var target = new PriorityValue(Owner, TestProperty, ValueStore); var source1 = new Source("1"); var source2 = new Source("2"); var source3 = new Source("3"); @@ -310,16 +310,5 @@ public IDisposable Subscribe(IObserver> observer) public void OnCompleted() => _observer.OnCompleted(); } - - private class MockSink : IValueSink - { - public void Completed(StyledPropertyBase property, IPriorityValueEntry entry, Optional oldValue) - { - } - - public void ValueChanged(AvaloniaPropertyChangedEventArgs change) - { - } - } } } diff --git a/tests/Avalonia.Base.UnitTests/Styling/SetterTests.cs b/tests/Avalonia.Base.UnitTests/Styling/SetterTests.cs index 40d2cab4a37..ef2586fcb76 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/SetterTests.cs +++ b/tests/Avalonia.Base.UnitTests/Styling/SetterTests.cs @@ -5,6 +5,7 @@ using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Data.Converters; +using Avalonia.Diagnostics; using Avalonia.Styling; using Moq; using Xunit; @@ -105,51 +106,51 @@ public void Setter_Should_Apply_Value_Without_Activator_With_Style_Priority() [Fact] public void Setter_Should_Apply_Value_With_Activator_As_Binding_With_StyleTrigger_Priority() { - var control = new Mock(); - var style = Mock.Of