using System; using System.Globalization; using System.Windows; using System.Windows.Media.Animation; namespace HandyControl.Interactivity; public abstract class Behavior : Animatable, IAttachedObject { private DependencyObject _associatedObject; private readonly Type _associatedType; internal Behavior(Type associatedType) { _associatedType = associatedType; } protected DependencyObject AssociatedObject { get { ReadPreamble(); return _associatedObject; } } protected Type AssociatedType { get { ReadPreamble(); return _associatedType; } } public void Attach(DependencyObject dependencyObject) { if (!Equals(dependencyObject, AssociatedObject)) { if (AssociatedObject != null) throw new InvalidOperationException(ExceptionStringTable .CannotHostBehaviorMultipleTimesExceptionMessage); if (dependencyObject != null && !AssociatedType.IsInstanceOfType(dependencyObject)) throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, ExceptionStringTable.TypeConstraintViolatedExceptionMessage, new object[] { GetType().Name, dependencyObject.GetType().Name, AssociatedType.Name })); WritePreamble(); _associatedObject = dependencyObject; WritePostscript(); OnAssociatedObjectChanged(); OnAttached(); } } public void Detach() { OnDetaching(); WritePreamble(); _associatedObject = null; WritePostscript(); OnAssociatedObjectChanged(); } DependencyObject IAttachedObject.AssociatedObject => AssociatedObject; internal event EventHandler AssociatedObjectChanged; protected override Freezable CreateInstanceCore() { return (Freezable) Activator.CreateInstance(GetType()); } private void OnAssociatedObjectChanged() { AssociatedObjectChanged?.Invoke(this, new EventArgs()); } protected virtual void OnAttached() { } protected virtual void OnDetaching() { } }