protected virtual void OnPropertyChanging <TValue>(
     object sender, string propertyName, PropertyChangeKind kind, TValue oldValue, TValue newValue
     )
 {
     if (!_IsPropertyChangingEmpty)
     {
         var e = new DetailedPropertyChangingEventArgs <TValue>(propertyName, kind, oldValue, newValue);
         OnPropertyChanging(sender, e);
     }
 }
        // ========================================
        // method
        // ========================================
        protected virtual void OnPropertyChanging(object sender, DetailedPropertyChangingEventArgs e)
        {
            if (!SuppressNotification)
            {
                var tmp = PropertyChanging;
                if (tmp != null)
                {
                    tmp(sender, e);
                }

                if (_namedPropertyChanging != null)
                {
                    _NamedPropertyChanging.Notify(sender, e.PropertyName, e);
                }
            }
        }
        //public virtual void NotifyPropertyRemovedMany<TValue>(object sender, string propertyName, TValue oldValue, int index) {
        //    NotifyPropertyChanged<TValue>(sender, propertyName, PropertyChangeKind.RemoveMany, oldValue, default(TValue), index);
        //}

        // === PropertyChangeNotifierBase ==========
        public virtual void NotifyPropertyChanging(object sender, DetailedPropertyChangingEventArgs e)
        {
            base.OnPropertyChanging(sender, e);
        }