private void SetPropagationVector(string prop, BindingInformations info) { if (!propagationVectors.ContainsKey(prop)) { propagationVectors.Add(prop, new List <BindingInformations>()); } var type = GetType(); var property = type.GetProperty(prop); var propertyType = property.PropertyType; info.Propagator = () => { var value = property.GetValue(this); // Gets the weak reference. info.Instance.TryGetTarget(out pObject instance); if (instance == null) { return; } switch (info.Direction) { case BindingMode.ReadOnly: break; case BindingMode.WriteOnly: case BindingMode.TwoWay: if (info.Adapter != null) { info.Property.SetValue(instance, info.Adapter.Invoke(value)); } else { info.Property.SetValue(instance, value); } break; default: throw new InvalidOperationException("Binding mode not supported."); } }; propagationVectors[prop].Add(info); }
/// <summary> /// Set a binding between a property of this class and a property of a /// target class. /// </summary> /// <param name="source">Source property.</param> /// <param name="target">Target <see cref="pObject"/> which have the target property.</param> /// <param name="destinationProperty">Target property to bind.</param> /// <param name="direction">Binding direction.</param> /// <param name="adapterToDestination">Function that convert the value to the destination variable type.</param> /// <param name="adapterToSource">Function that convert the value to the source variable type.</param> public void Bind(string source, pObject target, string destinationProperty, BindingMode direction, Func <object, object> adapterToDestination, Func <object, object> adapterToSource) { var sourceType = GetType(); var sourceProperty = sourceType.GetProperty(source); var destinationType = GetType(); var destProperty = sourceType.GetProperty(destinationProperty); Bindable sourceAttribute = null; Bindable destAttribute = null; if (source == destinationProperty && target == this) { throw new Exception("Cannot bind a property to itself."); } if (sourceProperty.PropertyType != destProperty.PropertyType) { switch (direction) { case BindingMode.TwoWay: if (adapterToDestination == null || adapterToSource == null) { throw new InvalidOperationException("Binding between two different types without adapter."); } break; case BindingMode.ReadOnly: if (adapterToDestination == null) { throw new InvalidOperationException("Binding between two different types without adapter."); } break; case BindingMode.WriteOnly: if (adapterToSource == null) { throw new InvalidOperationException("Binding between two different types without adapter."); } break; default: throw new InvalidOperationException("Binding mode not supported."); } } try { sourceAttribute = sourceProperty.GetCustomAttribute(typeof(Bindable)) as Bindable; destAttribute = destProperty.GetCustomAttribute(typeof(Bindable)) as Bindable; } catch (NullReferenceException) { throw new InvalidOperationException("One of this properties has no bindable attribute"); } if (sourceAttribute == null || destAttribute == null) { throw new InvalidOperationException("One of this properties has no bindable attribute"); } switch (direction) { case BindingMode.TwoWay: if (sourceAttribute.Direction != BindingMode.TwoWay || destAttribute.Direction != BindingMode.TwoWay) { throw new InvalidOperationException("TwoWay binding is not allowed for this binding."); } break; case BindingMode.ReadOnly: if ((sourceAttribute.Direction != BindingMode.WriteOnly && sourceAttribute.Direction != BindingMode.TwoWay) || (destAttribute.Direction != BindingMode.TwoWay && destAttribute.Direction != BindingMode.ReadOnly)) { throw new InvalidOperationException("ReadOnly binding is not allowed for this binding."); } break; case BindingMode.WriteOnly: if ((sourceAttribute.Direction != BindingMode.ReadOnly && sourceAttribute.Direction != BindingMode.TwoWay) || (destAttribute.Direction != BindingMode.TwoWay && destAttribute.Direction != BindingMode.WriteOnly)) { throw new InvalidOperationException("WriteOnly binding is not allowed for this binding."); } break; default: throw new InvalidOperationException("Binding mode not supported."); } var sourceBindingInformations = new BindingInformations { Instance = new WeakReference <pObject>(target), Property = target.GetType().GetProperty(destinationProperty), Direction = direction, Adapter = adapterToDestination }; BindingMode invertedDirection = BindingMode.TwoWay; switch (direction) { case BindingMode.ReadOnly: invertedDirection = BindingMode.WriteOnly; break; case BindingMode.WriteOnly: invertedDirection = BindingMode.ReadOnly; break; case BindingMode.TwoWay: invertedDirection = BindingMode.TwoWay; break; default: throw new InvalidOperationException("Binding mode not supported."); } var destBindingInformations = new BindingInformations { Instance = new WeakReference <pObject>(this), Property = GetType().GetProperty(source), Direction = invertedDirection, Adapter = adapterToSource }; SetPropagationVector(source, sourceBindingInformations); target.SetPropagationVector(destinationProperty, destBindingInformations); checkBindings(this, new System.ComponentModel.PropertyChangedEventArgs(source)); target.checkBindings(this, new System.ComponentModel.PropertyChangedEventArgs(destinationProperty)); }