Beispiel #1
0
        /// <summary>
        /// Strongly bind to PropertyChanged events for a particular property on a particular object
        /// </summary>
        /// <example>someObject.Bind(x => x.PropertyNameToBindTo, newValue => /* do something with the new value */)</example>
        /// <typeparam name="TSource">Type of object providing the PropertyChanged event</typeparam>
        /// <typeparam name="TProperty">Type of property for which the event is raised</typeparam>
        /// <param name="target">Object raising the PropertyChanged event you're interested in</param>
        /// <param name="targetSelector">MemberExpression selecting the property to observe for changes (e.g x => x.PropertyName)</param>
        /// <param name="handler">Handler called whenever that property changed</param>
        /// <returns>Something which can be used to undo the binding. You can discard it if you want</returns>
        ///

        public static IEventBinding Bind <TSource, TProperty>(this TSource target, Expression <Func <TSource, TProperty> > targetSelector, EventHandler <PropertyChangedExtendedEventArgs <TProperty> > handler) where TSource : class, INotifyPropertyChanged
        {
            var propertyNamee         = targetSelector.ToString();
            MemberExpression member   = targetSelector.Body as MemberExpression;
            PropertyInfo     propInfo = member.Member as PropertyInfo;
            var propertyName          = propInfo.Name;

            var propertyAccess = targetSelector.Compile();
            // Make sure we don't capture target strongly, otherwise we'll retain it when we shouldn't
            // If it does get released, we're released from the delegate list
            var weakTarget = new WeakReference <TSource>(target);

            PropertyChangedEventHandler ourHandler = (o, e) =>
            {
                if (e.PropertyName == propertyName || e.PropertyName == String.Empty)
                {
                    TSource strongTarget;
                    if (weakTarget.TryGetTarget(out strongTarget))
                    {
                        handler(strongTarget, new PropertyChangedExtendedEventArgs <TProperty>(propertyName, propertyAccess(strongTarget)));
                    }
                }
            };

            target.PropertyChanged += ourHandler;

            var listener = new StrongPropertyChangedBinding(target, ourHandler);

            return(listener);
        }
        private static IEventBinding BindImpl <TSource, TProperty>(TSource target, Expression <Func <TSource, TProperty> > targetSelector, EventHandler <PropertyChangedExtendedEventArgs <TProperty> > handler, bool invoke) where TSource : class, INotifyPropertyChanged
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (targetSelector == null)
            {
                throw new ArgumentNullException(nameof(targetSelector));
            }
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            var propertyName   = targetSelector.NameForProperty();
            var propertyAccess = targetSelector.Compile();
            // Make sure we don't capture target strongly, otherwise we'll retain it when we shouldn't
            // If it does get released, we're released from the delegate list
            var weakTarget = new WeakReference <TSource>(target);

            void ourHandler(object o, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == propertyName || e.PropertyName == String.Empty)
                {
                    if (weakTarget.TryGetTarget(out TSource strongTarget))
                    {
                        handler(strongTarget, new PropertyChangedExtendedEventArgs <TProperty>(propertyName, propertyAccess(strongTarget)));
                    }
                }
            }

            target.PropertyChanged += ourHandler;

            var listener = new StrongPropertyChangedBinding(target, ourHandler);

            if (invoke)
            {
                handler(target, new PropertyChangedExtendedEventArgs <TProperty>(propertyName, propertyAccess(target)));
            }

            return(listener);
        }