private void BuildBinding(Expression <Func <TTargetMember> > bindTarget, Expression <Func <TSourceMember> > bindSource, Func <TSourceMember, TTargetMember> valueConverter, bool applyLeft) { _targetReference = bindTarget.Body as MemberExpression; _sourceReference = bindSource.Body as MemberExpression; if (_targetReference == null) { throw new ArgumentException($"{nameof(bindTarget)} is expected to contain a MemberExpression, instead it got {bindTarget.Body.NodeType}."); } if (_sourceReference == null) { throw new ArgumentException($"{nameof(bindSource)} is expected to contain a MemberExpression, instead it got {bindSource.Body.NodeType}."); } _targetInstance = ExpressionHelper.EvaluateExpression(_targetReference.Expression); _sourceInstance = ExpressionHelper.EvaluateExpression(_sourceReference.Expression) as INotifyPropertyChanged; if (bindTarget == null) { throw new ArgumentException($"{nameof(bindTarget)} must be the member of an instance."); } if (_sourceInstance == null) { throw new ArgumentException($"{nameof(bindSource)} must be the member of an instance that implements {nameof(INotifyPropertyChanged)}."); } _targetProperty = BindManager.GetBindEndpoint(_targetInstance).GetMemberAsTarget(_targetReference.Member, this); _sourceProperty = BindManager.GetBindEndpoint(_sourceInstance).GetMemberAsSource(_sourceReference.Member, this); if (valueConverter == null) { // Default just directly applies the value of bindSource to bindTarget ApplyToTargetCall = Expression.Lambda <Action>(Expression.Assign(_targetReference, _sourceReference)).Compile(); } else { // Converter was provided so we package it into an Action to call later Action <TTargetMember> setTargetAction = ExpressionHelper.MakeAssignmentAction <TTargetMember>(_targetProperty.SetMethod, _targetInstance); Func <TSourceMember> getSourceFunction = ExpressionHelper.MakeGetFunc <TSourceMember>(_sourceProperty.GetMethod, _sourceInstance); ApplyToTargetCall = () => setTargetAction.Invoke(valueConverter(getSourceFunction())); } _sourceInstance.PropertyChanged += (sender, e) => { if (_sourceProperty.Name == e.PropertyName && this.Enabled) { Run(); } }; _enabled = true; if (applyLeft) { Run(); } }
/// <summary> /// Gets a list of all bindings where a member of this instance is the target of the bind. /// </summary> public static IReadOnlyCollection <Binding> GetTargetedBindings(this INotifyPropertyChanged instance) { return(BindManager.GetBindEndpoint(instance).CachedMembers.SelectMany(d => d.Value.TargetBindings).ToList <Binding>().AsReadOnly()); }