using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace System.Application.Mvvm { /// /// 属性更改通知事件 /// [Serializable] public class NotificationObject : INotifyPropertyChanged { /// /// 属性更改通知事件 /// [field: NonSerialized] public event PropertyChangedEventHandler? PropertyChanged; /// /// 引发属性更改通知事件 /// /// /// () => lambda表达式属性 /// () => 指定了具有非属性格式的Lambda表达式 [NotifyPropertyChangedInvocator] // ReSharper disable once UnusedParameter.Global protected virtual void RaisePropertyChanged(ref T source, [NotNull] Expression> propertyExpression) { if (propertyExpression == null) throw new ArgumentNullException(nameof(propertyExpression)); if (!(propertyExpression.Body is MemberExpression)) throw new NotSupportedException("此方法仅允许使用 ()=> properties形式的lambda表达式"); var memberExpression = (MemberExpression)propertyExpression.Body; RaisePropertyChanged(memberExpression.Member.Name); } /// /// 引发属性更改通知事件 /// /// 属性名称 [NotifyPropertyChangedInvocator] protected virtual void RaisePropertyChanged([CallerMemberName][DisallowNull] string propertyName = "") { var threadSafeHandler = Interlocked.CompareExchange(ref PropertyChanged, null, null); threadSafeHandler?.Invoke(this, EventArgsFactory.GetPropertyChangedEventArgs(propertyName)); } /// /// 如果该值与上一个值不同,则将其更改并引发属性更改通知事件。 /// /// 属性泛型 /// 原始值 /// 新值 /// 属性名称数组,当此属性更改时会触发PropertyChanged事件 /// 属性名称 /// 值是否已更改 [NotifyPropertyChangedInvocator] protected bool RaisePropertyChangedIfSet(ref T source, T value, string[]? relatedProperties = null, [CallerMemberName] string propertyName = null) { //如果值相同则什么都不做 if (EqualityComparer.Default.Equals(source, value)) return false; source = value; RaisePropertyChanged(propertyName); if (relatedProperties == null) return true; foreach (var p in relatedProperties) RaisePropertyChanged(p); return true; } /// /// 如果该值与上一个值不同,则将其更改并引发属性更改通知事件。 /// /// 属性泛型 /// 原始值 /// 新值 /// 属性名称字符串,当此属性更改时会触发PropertyChanged事件 /// 属性名称 /// 值是否已更改 [NotifyPropertyChangedInvocator] protected bool RaisePropertyChangedIfSet(ref T source, T value, string relatedProperty, [CallerMemberName] string propertyName = null) { return RaisePropertyChangedIfSet(ref source, value, new[] { relatedProperty }, propertyName); } } }