Exemple #1
0
        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);
        }
Exemple #2
0
        /// <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));
        }