/// <summary> /// Initializes a new instance of the <see cref="PropertyBinding"/> class. /// </summary> /// <param name="sourceProperty">The source property details.</param> /// <param name="targetProperty">The target property details.</param> /// <param name="direction">The direction of the binding.</param> public PropertyBinding(PropertyDetails sourceProperty, PropertyDetails targetProperty, PropertyBindingDirection direction) { SourceProperty = sourceProperty; TargetProperty = targetProperty; Direction = direction; UpdateFromDefault(); }
/// <summary> /// Binds the value of a property of a source object to a property of a target object. /// Whenever either property is changed, the other side of the binding is set to the same /// value. To avoid endless loops, the PropertyChanged event must only be raised when the /// value actually changed, not already on assignment. The target property is updated /// immediately after setting up the binding, if <paramref name="direction"/> is not /// OneWayToSource. /// </summary> /// <typeparam name="TTarget">Type that defines the target property.</typeparam> /// <typeparam name="TSource">Type that defines the source property.</typeparam> /// <typeparam name="TProperty">Value type of both properties.</typeparam> /// <param name="target">Instance of the type that defines the target property. Must implement INotifyPropertyChanged.</param> /// <param name="targetExpr">Lambda expression of the target property.</param> /// <param name="source">Instance of the type that defines the source property. Must implement INotifyPropertyChanged.</param> /// <param name="sourceExpr">Lambda expression of the source property.</param> /// <param name="direction">The direction of property value updates.</param> /// <example> /// Bind a source property to a local property of the same type: /// <code> /// this.BindProperty(me => me.TargetProperty, source, src => src.SourceProperty); /// </code> /// </example> public static void BindProperty <TTarget, TSource, TProperty>( this TTarget target, Expression <Func <TTarget, TProperty> > targetExpr, TSource source, Expression <Func <TSource, TProperty> > sourceExpr, PropertyBindingDirection direction = PropertyBindingDirection.TwoWay) where TTarget : INotifyPropertyChanged where TSource : INotifyPropertyChanged { // Initialise all expression parts and reflected properties var targetMemberExpr = targetExpr.Body as MemberExpression; if (targetMemberExpr == null) { throw new ArgumentException("Unsupported target expression type."); } PropertyInfo targetProperty = targetMemberExpr.Member as PropertyInfo; if (targetProperty == null) { throw new ArgumentException("Unsupported target expression type."); } var sourceMemberExpr = sourceExpr.Body as MemberExpression; if (sourceMemberExpr == null) { throw new ArgumentException("Unsupported source expression type."); } PropertyInfo sourceProperty = sourceMemberExpr.Member as PropertyInfo; if (sourceProperty == null) { throw new ArgumentException("Unsupported source expression type."); } if (direction != PropertyBindingDirection.OneWayToSource) { // When the source changes, update the target source.PropertyChanged += (s, e) => { if (e.PropertyName == sourceProperty.Name) { targetProperty.SetValue( target, sourceProperty.GetValue(source, null), null); } }; } if (direction != PropertyBindingDirection.OneWayToTarget) { // When the target changes, update the source target.PropertyChanged += (s, e) => { if (e.PropertyName == targetProperty.Name) { sourceProperty.SetValue( source, targetProperty.GetValue(target, null), null); } }; } if (direction != PropertyBindingDirection.OneWayToSource) { // Update the target immediately targetProperty.SetValue( target, sourceProperty.GetValue(source, null), null); } }
/// <summary> /// Creates a property binding with the given source property and target property. /// </summary> /// <param name="sourceProperty">The source property.</param> /// <param name="targetProperty">The target property.</param> /// <param name="direction">The direction of the property binding.</param> /// <returns>A generated property binding.</returns> public static PropertyBinding Create <TSource, TTarget>(PropertyDetails <TSource> sourceProperty, PropertyDetails <TTarget> targetProperty, PropertyBindingDirection direction) => new PropertyBinding <TSource, TTarget>(sourceProperty, targetProperty, direction);
/// <summary> /// Creates a property binding with the given source property and target property. /// </summary> /// <param name="sourceProperty">The source property.</param> /// <param name="targetProperty">The target property.</param> /// <param name="direction">The direction of the property binding.</param> /// <returns>A generated property binding.</returns> public static PropertyBinding Create <TSource, TTarget>(Expression <Func <TSource> > sourceProperty, Expression <Func <TTarget> > targetProperty, PropertyBindingDirection direction) => new PropertyBinding <TSource, TTarget>(sourceProperty, targetProperty, direction);
/// <summary> /// Creates a property binding with the given source property and target property. /// </summary> /// <param name="sourceProperty">The source property.</param> /// <param name="targetProperty">The target property.</param> /// <returns>A generated property binding.</returns> public static PropertyBinding Create(PropertyDetails sourceProperty, PropertyDetails targetProperty, PropertyBindingDirection direction) { var propertyBindingType = typeof(PropertyBinding <,>).MakeGenericType(sourceProperty.Type, targetProperty.Type); return((PropertyBinding)propertyBindingType.CreateInstance(sourceProperty, targetProperty, direction)); }