¡Hay que guardar esto en lugar seguro! Propiedad Adjunta genérica con objeto asociado, On The Rocks!

Señoras y señores, gracias a un tipo llamado Bary Nusz (http://blog.falafel.com/blogs/BaryNusz) y sacándole código del blog he conseguid (ha conseguido) realizar una cosa flipante:

<Button x:Name=”boton”
            WpfApplication1:MouseDownTiming.Value=”{Binding ElementName=boton, Path=Focusable}”

 

¿Qué es esto? Una propiedad adjunta que se enlaza a la propiedad Focusable… bueno, realmente he desechado la solución con esta artimaña, pero aquí dejo presente lo que había en el condumio.

Principalmente:

AttachedPropertyAssociatedObject.cs

using System;

using System.Collections.Generic;

using System.Windows;

 

namespace WpfApplication1

{

    public abstract class AttachedPropertyAssociatedObject<O, T, A> : DependencyObject

        where T : DependencyObject

        where O : AttachedPropertyAssociatedObject<O, T, A>, new()

    {

        static Type _type = typeof(O);

 

        public T AssociatedObject { get; private set; }

 

        public AttachedPropertyAssociatedObject()

        { }

 

        public AttachedPropertyAssociatedObject(T associatedObject)

        {

            AssociatedObject = associatedObject;

        }

 

        public static readonly DependencyProperty ValueProperty =

                            DependencyProperty.RegisterAttached(

        "Value",

        typeof(A),

        typeof(AttachedPropertyAssociatedObject<O, T, A>),

#if Silverlight

 new FrameworkPropertyMetadata(false, OnValueChanged));

#else

 new PropertyMetadata(OnValueChanged));

#endif

 

        public static A GetValue(DependencyObject d)

        {

            return (A)d.GetValue(ValueProperty);

        }

 

        public static void SetValue(DependencyObject d, A value)

        {

            d.SetValue(ValueProperty, value);

        }

 

        public static void AddValueChangedHandler(DependencyObject sender, PropertyChangedCallback callback)

        {

            Dictionary<Type, PropertyChangedCallback> propertyChangedCallbackDictionary =

                GenericAttachedPropertyChangedCallbackDictionary.GetValue(sender);

            if (propertyChangedCallbackDictionary == null)

            {

                propertyChangedCallbackDictionary = new Dictionary<Type, PropertyChangedCallback>();

                sender.SetValue(GenericAttachedPropertyChangedCallbackDictionary.ValueProperty, propertyChangedCallbackDictionary);

            }

            if (propertyChangedCallbackDictionary.ContainsKey(_type))

            {

                propertyChangedCallbackDictionary[_type] += callback;

            }

            else

            {

                propertyChangedCallbackDictionary[_type] = callback;

            }

        }

 

        public static void RemoveValueChangedHandler(DependencyObject sender, PropertyChangedCallback callback)

        {

            Dictionary<Type, PropertyChangedCallback> propertyChangedCallbackDictionary =

                GenericAttachedPropertyChangedCallbackDictionary.GetValue(sender);

 

            if ((propertyChangedCallbackDictionary != null) &&

                           (propertyChangedCallbackDictionary.ContainsKey(_type)))

            {

                propertyChangedCallbackDictionary[_type] -= callback;

            }

        }

 

        private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            T associatedObject = d as T;

            if (associatedObject == null)

            {

                throw new Exception(String.Format("DependencyObject must be of type {0}", typeof(T)));

            }

 

            O attachedPropertyAssociatedObject = GenericAttachedProperty<O>.GetValue(d);

            if (e.NewValue != null)

            {

                if (attachedPropertyAssociatedObject == null)

                {

                    attachedPropertyAssociatedObject = new O();

                    attachedPropertyAssociatedObject.AssociatedObject = associatedObject;

 

                    GenericAttachedProperty<O>.SetValue(associatedObject, attachedPropertyAssociatedObject);

                    attachedPropertyAssociatedObject.Initialize();

                }

                else

                {

                    Dictionary<Type, PropertyChangedCallback> propertyChangedCallbackDictionary =

                        GenericAttachedPropertyChangedCallbackDictionary.GetValue(associatedObject);

 

                    if ((propertyChangedCallbackDictionary != null) &&

                                           (propertyChangedCallbackDictionary.ContainsKey(_type)))

                    {

                        PropertyChangedCallback callback = propertyChangedCallbackDictionary[_type];

                        if (callback != null)

                        {

                            callback(associatedObject, e);

                        }

                    }

                }

            }

            else

            {

                if (attachedPropertyAssociatedObject != null)

                {

                    attachedPropertyAssociatedObject.UnInitialize();

                    GenericAttachedProperty<O>.SetValue(attachedPropertyAssociatedObject, null);

                }

            }

        }

 

        public virtual void Initialize()

        {

        }

 

        public virtual void UnInitialize()

        {

        }

    }

 

 

    public class GenericAttachedProperty<T>

    {

        public static readonly DependencyProperty ValueProperty =

                       DependencyProperty.RegisterAttached(

        "Value",

        typeof(T),

        typeof(GenericAttachedProperty<T>),

        null);

 

        public static T GetValue(DependencyObject d)

        {

            return (T)d.GetValue(ValueProperty);

        }

 

        public static void SetValue(DependencyObject d, T value)

        {

            d.SetValue(ValueProperty, value);

        }

    }

}

GenericAttachedProperty.cs

using System.Windows;

 

namespace WpfApplication1

{

    public abstract class GenericAttachedProperty<O, A>

    {

        public static readonly DependencyProperty ValueProperty =

            DependencyProperty.RegisterAttached(

                "Value",

                typeof(A),

                typeof(GenericAttachedProperty<O, A>),

                null);

 

        public static A GetValue(DependencyObject d)

        {

            return (A)d.GetValue(ValueProperty);

        }

 

        public static void SetValue(DependencyObject d, A value)

        {

            d.SetValue(ValueProperty, value);

        }

    }

}

GenericAttachedPropertyChangedCallbackDictionary.cs

namespace WpfApplication1

{

 class 

GenericAttachedPropertyChangedCallbackDictionary 

:

 

GenericAttachedProperty<GenericAttachedPropertyChangedCallbackDictionary, 

Dictionary<Type, PropertyChangedCallback>> { }

}

Y mi clasecilla personalizada:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Input;

using System.Windows.Threading;

 

namespace WpfApplication1

{

    class MouseDownTiming : AttachedPropertyAssociatedObject<MouseDownTiming, FrameworkElement, bool>

    {

 

        public override void Initialize()

        {

            AssociatedObject.PreviewMouseDown += AssociatedObjectOnPreviewMouseDown;

            AssociatedObject.PreviewMouseUp += AssociatedObjectOnPreviewMouseUp;

            AssociatedObject.SetValue(ValueProperty, false);

            SetTimer(AssociatedObject, new DispatcherTimer());

        }

 

        private void AssociatedObjectOnPreviewMouseUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)

        {

            var timer = (DispatcherTimer)AssociatedObject.GetValue(TimerProperty);

            timer.IsEnabled = false;

            AssociatedObject.SetValue(ValueProperty, false);

        }

 

        public override void UnInitialize()

        {

            AssociatedObject.PreviewMouseDown -= AssociatedObjectOnPreviewMouseDown;

        }

 

        private void AssociatedObjectOnPreviewMouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)

        {

            var timer = (DispatcherTimer)AssociatedObject.GetValue(TimerProperty);

            timer.IsEnabled = true;

        }

 

        #region Timeout

 

        /// <summary>

        /// Timeout Attached Dependency Property

        /// </summary>

        public static readonly DependencyProperty TimeoutProperty =

            DependencyProperty.RegisterAttached("Timeout", typeof(TimeSpan), typeof(MouseDownTiming),

                new FrameworkPropertyMetadata(TimeSpan.FromSeconds(1),

                    OnTimeoutChanged));

 

        /// <summary>

        /// Gets the Timeout property. This dependency property 

        /// indicates ....

        /// </summary>

        public static TimeSpan GetTimeout(DependencyObject d)

        {

            return (TimeSpan)d.GetValue(TimeoutProperty);

        }

 

        /// <summary>

        /// Sets the Timeout property. This dependency property 

        /// indicates ....

        /// </summary>

        public static void SetTimeout(DependencyObject d, TimeSpan value)

        {

            d.SetValue(TimeoutProperty, value);

        }

 

        /// <summary>

        /// Handles changes to the Timeout property.

        /// </summary>

        private static void OnTimeoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            TimeSpan oldTimeout = (TimeSpan)e.OldValue;

            TimeSpan newTimeout = (TimeSpan)d.GetValue(TimeoutProperty);

 

            var timer = (DispatcherTimer) d.GetValue(TimerProperty);

            if (timer == null)

            {

                timer=(DispatcherTimer) CoerceTimer(d, e);

                SetTimer(d, timer);

            }           

 

            timer.Interval = newTimeout;

        }

 

        #endregion        

 

        #region Timer

 

        /// <summary>

        /// Timer Read-Only Dependency Property

        /// </summary>

        private static readonly DependencyPropertyKey TimerPropertyKey

            = DependencyProperty.RegisterAttachedReadOnly("Timer", typeof(DispatcherTimer), typeof(MouseDownTiming),

                new FrameworkPropertyMetadata(null,

                    new PropertyChangedCallback(OnTimerChanged),

                    new CoerceValueCallback(CoerceTimer)));

 

        public static readonly DependencyProperty TimerProperty

            = TimerPropertyKey.DependencyProperty;

 

        /// <summary>

        /// Gets the Timer property. This dependency property 

        /// indicates ....

        /// </summary>

        public static DispatcherTimer GetTimer(DependencyObject d)

        {

            return (DispatcherTimer)d.GetValue(TimerProperty);

        }

 

        /// <summary>

        /// Provides a secure method for setting the Timer property.  

        /// This dependency property indicates ....

        /// </summary>

        private static void SetTimer(DependencyObject d, DispatcherTimer value)

        {

            d.SetValue(TimerPropertyKey, value);

        }

 

        /// <summary>

        /// Handles changes to the Timer property.

        /// </summary>

        private static void OnTimerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            DispatcherTimer oldTimer = (DispatcherTimer)e.OldValue;

            DispatcherTimer newTimer = (DispatcherTimer)d.GetValue(TimerProperty);

 

            newTimer.Interval = (TimeSpan)d.GetValue(TimeoutProperty);

 

            newTimer.Tick += (sender, args) =>

            {

                d.SetValue(ValueProperty, true);

                var timer = (DispatcherTimer) d.GetValue(TimerProperty);

                

                timer.IsEnabled = false;

            };

        }

 

        /// <summary>

        /// Coerces the Timer value.

        /// </summary>

        private static object CoerceTimer(DependencyObject d, object value)

        {

            DispatcherTimer timer=new DispatcherTimer();

            timer.Interval = (TimeSpan) d.GetValue(TimeoutProperty);

            return timer;

        }

 

        #endregion

    }

}

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s