using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ImageCatalog_2 { public class ViewModelBase : INotifyPropertyChanged { private readonly SynchronizationContext? _synchronizationContext; protected ViewModelBase() { // Capture the synchronization context (UI thread context) _synchronizationContext = SynchronizationContext.Current; } public event PropertyChangedEventHandler? PropertyChanged; // This method is called by the Set accessor of each property. // The CallerMemberName attribute that is applied to the optional propertyName // parameter causes the property name of the caller to be substituted as an argument. protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "") { if (PropertyChanged == null) return; if (_synchronizationContext != null && SynchronizationContext.Current != _synchronizationContext) { // We're on a different thread, marshal to the UI thread _synchronizationContext.Send(_ => { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }, null); } else { // We're already on the UI thread or no sync context available PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }