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/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.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/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml b/src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml
index 3bfe511fbc..1b5f431f36 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml
+++ b/src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml
@@ -16,6 +16,8 @@