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/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);
}
}