diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 2c9efc7767..d89d6f3690 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -664,14 +664,12 @@ namespace Avalonia
/// The property that has changed.
/// The old property value.
/// The new property value.
- /// The priority of the binding that produced the value.
protected void RaisePropertyChanged(
DirectPropertyBase property,
- Optional oldValue,
- BindingValue newValue,
- BindingPriority priority = BindingPriority.LocalValue)
+ T oldValue,
+ T newValue)
{
- RaisePropertyChanged(property, oldValue, newValue, priority, true);
+ RaisePropertyChanged(property, oldValue, newValue, BindingPriority.LocalValue, true);
}
///
@@ -720,7 +718,7 @@ namespace Avalonia
///
/// True if the value changed, otherwise false.
///
- protected bool SetAndRaise(AvaloniaProperty property, ref T field, T value)
+ protected bool SetAndRaise(DirectPropertyBase property, ref T field, T value)
{
VerifyAccess();
diff --git a/src/Avalonia.Base/Data/Core/IndexerNodeBase.cs b/src/Avalonia.Base/Data/Core/IndexerNodeBase.cs
index 9ec256225b..57e4fa4a8e 100644
--- a/src/Avalonia.Base/Data/Core/IndexerNodeBase.cs
+++ b/src/Avalonia.Base/Data/Core/IndexerNodeBase.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Data.Core
if (target is INotifyPropertyChanged inpc)
{
- WeakEvents.PropertyChanged.Subscribe(inpc, this);
+ WeakEvents.ThreadSafePropertyChanged.Subscribe(inpc, this);
}
ValueChanged(GetValue(target));
@@ -39,7 +39,7 @@ namespace Avalonia.Data.Core
if (target is INotifyPropertyChanged inpc)
{
- WeakEvents.PropertyChanged.Unsubscribe(inpc, this);
+ WeakEvents.ThreadSafePropertyChanged.Unsubscribe(inpc, this);
}
}
}
diff --git a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
index 7c2caf02b4..e8e3e6d509 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
@@ -160,7 +160,7 @@ namespace Avalonia.Data.Core.Plugins
var inpc = GetReferenceTarget() as INotifyPropertyChanged;
if (inpc != null)
- WeakEvents.PropertyChanged.Unsubscribe(inpc, this);
+ WeakEvents.ThreadSafePropertyChanged.Unsubscribe(inpc, this);
}
private object? GetReferenceTarget()
@@ -185,7 +185,7 @@ namespace Avalonia.Data.Core.Plugins
var inpc = GetReferenceTarget() as INotifyPropertyChanged;
if (inpc != null)
- WeakEvents.PropertyChanged.Subscribe(inpc, this);
+ WeakEvents.ThreadSafePropertyChanged.Subscribe(inpc, this);
}
}
}
diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs
index 2cdb973174..5b8dac2f53 100644
--- a/src/Avalonia.Base/StyledElement.cs
+++ b/src/Avalonia.Base/StyledElement.cs
@@ -524,13 +524,7 @@ namespace Avalonia
NotifyResourcesChanged();
}
-#nullable disable
- RaisePropertyChanged(
- ParentProperty,
- new Optional(old),
- new BindingValue(Parent),
- BindingPriority.LocalValue);
-#nullable enable
+ RaisePropertyChanged(ParentProperty, old, Parent);
}
}
diff --git a/src/Avalonia.Base/Utilities/WeakEvents.cs b/src/Avalonia.Base/Utilities/WeakEvents.cs
index 6da899bab2..2f62564e0e 100644
--- a/src/Avalonia.Base/Utilities/WeakEvents.cs
+++ b/src/Avalonia.Base/Utilities/WeakEvents.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Input;
+using Avalonia.Threading;
namespace Avalonia.Utilities;
@@ -20,15 +21,30 @@ public class WeakEvents
});
///
- /// Represents PropertyChanged event from
+ /// Represents PropertyChanged event from with auto-dispatching to the UI thread
///
public static readonly WeakEvent
- PropertyChanged = WeakEvent.Register(
+ ThreadSafePropertyChanged = WeakEvent.Register(
(s, h) =>
{
- PropertyChangedEventHandler handler = (_, e) => h(s, e);
+ bool unsubscribed = false;
+ PropertyChangedEventHandler handler = (_, e) =>
+ {
+ if (Dispatcher.UIThread.CheckAccess())
+ h(s, e);
+ else
+ Dispatcher.UIThread.Post(() =>
+ {
+ if (!unsubscribed)
+ h(s, e);
+ });
+ };
s.PropertyChanged += handler;
- return () => s.PropertyChanged -= handler;
+ return () =>
+ {
+ unsubscribed = true;
+ s.PropertyChanged -= handler;
+ };
});
diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs
index 87bb1d3790..8b0cc06136 100644
--- a/src/Avalonia.Base/Visual.cs
+++ b/src/Avalonia.Base/Visual.cs
@@ -573,7 +573,7 @@ namespace Avalonia
/// The new visual parent.
protected virtual void OnVisualParentChanged(Visual? oldParent, Visual? newParent)
{
- RaisePropertyChanged(VisualParentProperty, oldParent, newParent, BindingPriority.LocalValue);
+ RaisePropertyChanged(VisualParentProperty, oldParent, newParent);
}
internal override ParametrizedLogger? GetBindingWarningLogger(
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index 065c4ff2e5..2ee32b0dda 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -345,10 +345,7 @@ namespace Avalonia.Controls.Primitives
if (_oldSelectedItems != SelectedItems)
{
- RaisePropertyChanged(
- SelectedItemsProperty,
- new Optional(_oldSelectedItems),
- new BindingValue(SelectedItems));
+ RaisePropertyChanged(SelectedItemsProperty, _oldSelectedItems, SelectedItems);
_oldSelectedItems = SelectedItems;
}
}
@@ -909,10 +906,7 @@ namespace Avalonia.Controls.Primitives
else if (e.PropertyName == nameof(InternalSelectionModel.WritableSelectedItems) &&
_oldSelectedItems != (Selection as InternalSelectionModel)?.SelectedItems)
{
- RaisePropertyChanged(
- SelectedItemsProperty,
- new Optional(_oldSelectedItems),
- new BindingValue(SelectedItems));
+ RaisePropertyChanged(SelectedItemsProperty, _oldSelectedItems, SelectedItems);
_oldSelectedItems = SelectedItems;
}
else if (e.PropertyName == nameof(ISelectionModel.Source))
diff --git a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
index 18cf96ddca..d2b91def7d 100644
--- a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
+++ b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
@@ -1,37 +1,30 @@
using Avalonia.Layout;
+using Avalonia.Threading;
namespace Avalonia.Controls
{
public partial class RelativePanel
{
- private static void OnAlignPropertiesChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
- {
- if (d is Layoutable layoutable && layoutable.Parent is Layoutable layoutableParent)
- {
- layoutableParent.InvalidateArrange();
- }
- }
static RelativePanel()
{
ClipToBoundsProperty.OverrideDefaultValue(true);
- AboveProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignBottomWithPanelProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignBottomWithProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignHorizontalCenterWithPanelProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignHorizontalCenterWithProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignLeftWithPanelProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignLeftWithProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignRightWithPanelProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignRightWithProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignTopWithPanelProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignTopWithProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignVerticalCenterWithPanelProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- AlignVerticalCenterWithProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- BelowProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- LeftOfProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
- RightOfProperty.Changed.AddClassHandler(OnAlignPropertiesChanged);
+ AffectsParentArrange(
+ AlignLeftWithPanelProperty, AlignLeftWithProperty, LeftOfProperty,
+ AlignRightWithPanelProperty, AlignRightWithProperty, RightOfProperty,
+ AlignTopWithPanelProperty, AlignTopWithProperty, AboveProperty,
+ AlignBottomWithPanelProperty, AlignBottomWithProperty, BelowProperty,
+ AlignHorizontalCenterWithPanelProperty, AlignHorizontalCenterWithProperty,
+ AlignVerticalCenterWithPanelProperty, AlignVerticalCenterWithProperty);
+
+ AffectsParentMeasure(
+ AlignLeftWithPanelProperty, AlignLeftWithProperty, LeftOfProperty,
+ AlignRightWithPanelProperty, AlignRightWithProperty, RightOfProperty,
+ AlignTopWithPanelProperty, AlignTopWithProperty, AboveProperty,
+ AlignBottomWithPanelProperty, AlignBottomWithProperty, BelowProperty,
+ AlignHorizontalCenterWithPanelProperty, AlignHorizontalCenterWithProperty,
+ AlignVerticalCenterWithPanelProperty, AlignVerticalCenterWithProperty);
}
///
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
index abb166a92b..9e58f81b55 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
@@ -121,7 +121,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
{
if (_reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc)
{
- WeakEvents.PropertyChanged.Unsubscribe(inpc, this);
+ WeakEvents.ThreadSafePropertyChanged.Unsubscribe(inpc, this);
}
}
@@ -138,7 +138,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
private void SubscribeToChanges()
{
if (_reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc)
- WeakEvents.PropertyChanged.Subscribe(inpc, this);
+ WeakEvents.ThreadSafePropertyChanged.Subscribe(inpc, this);
}
}