/// <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); }