Esempio n. 1
0
        /// <summary>
        ///     Applies the binding expression to a previously set source or target.
        /// </summary>
        void ApplyCore(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget = false)
        {
            BindingMode mode = Binding.GetRealizedMode(_targetProperty);

            if ((mode == BindingMode.OneWay || mode == BindingMode.OneTime) && fromTarget)
            {
                return;
            }

            bool needsGetter = (mode == BindingMode.TwoWay && !fromTarget) || mode == BindingMode.OneWay || mode == BindingMode.OneTime;
            bool needsSetter = !needsGetter && ((mode == BindingMode.TwoWay && fromTarget) || mode == BindingMode.OneWayToSource);

            object current             = sourceObject;
            BindingExpressionPart part = null;

            for (var i = 0; i < _parts.Count; i++)
            {
                part = _parts[i];

                if (!part.IsSelf && current != null)
                {
                    // Allow the object instance itself to provide its own TypeInfo
                    TypeInfo currentType = current is IReflectableType reflectable?reflectable.GetTypeInfo() : current.GetType().GetTypeInfo();

                    if (part.LastGetter == null || !part.LastGetter.DeclaringType.GetTypeInfo().IsAssignableFrom(currentType))
                    {
                        SetupPart(currentType, part);
                    }

                    if (i < _parts.Count - 1)
                    {
                        part.TryGetValue(current, out current);
                    }
                }

                if (!part.IsSelf &&
                    current != null &&
                    ((needsGetter && part.LastGetter == null) ||
                     (needsSetter && part.NextPart == null && part.LastSetter == null)))
                {
                    BindingDiagnostics.SendBindingFailure(Binding, current, target, property, "Binding", PropertyNotFoundErrorMessage, part.Content, current, target.GetType(), property.PropertyName);
                    break;
                }

                if (part.NextPart != null && (mode == BindingMode.OneWay || mode == BindingMode.TwoWay) &&
                    current is INotifyPropertyChanged inpc)
                {
                    part.Subscribe(inpc);
                }
            }

            Debug.Assert(part != null, "There should always be at least the self part in the expression.");

            if (needsGetter)
            {
                if (part.TryGetValue(current, out object value) || part.IsSelf)
                {
                    value = Binding.GetSourceValue(value, property.ReturnType);
                }
                else
                {
                    value = Binding.FallbackValue ?? property.GetDefaultValue(target);
                }

                if (!TryConvert(ref value, property, property.ReturnType, true))
                {
                    BindingDiagnostics.SendBindingFailure(Binding, current, target, property, "Binding", CannotConvertTypeErrorMessage, value, property.ReturnType);
                    return;
                }

                target.SetValueCore(property, value, SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted);
            }
            else if (needsSetter && part.LastSetter != null && current != null)
            {
                object value = Binding.GetTargetValue(target.GetValue(property), part.SetterType);

                if (!TryConvert(ref value, property, part.SetterType, false))
                {
                    BindingDiagnostics.SendBindingFailure(Binding, current, target, property, "Binding", CannotConvertTypeErrorMessage, value, part.SetterType);
                    return;
                }

                object[] args;
                if (part.IsIndexer)
                {
                    args = new object[part.Arguments.Length + 1];
                    part.Arguments.CopyTo(args, 0);
                    args[args.Length - 1] = value;
                }
                else if (part.IsBindablePropertySetter)
                {
                    args = new[] { part.BindablePropertyField, value };
                }
                else
                {
                    args = new[] { value };
                }

                part.LastSetter.Invoke(current, args);
            }
        }
Esempio n. 2
0
        /// <summary>
        ///     Applies the binding expression to a previously set source or target.
        /// </summary>
        void ApplyCore(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget = false)
        {
            BindingMode mode = Binding.GetRealizedMode(_targetProperty);

            if ((mode == BindingMode.OneWay || mode == BindingMode.OneTime) && fromTarget)
            {
                return;
            }

            bool needsGetter = (mode == BindingMode.TwoWay && !fromTarget) || mode == BindingMode.OneWay || mode == BindingMode.OneTime;
            bool needsSetter = !needsGetter && ((mode == BindingMode.TwoWay && fromTarget) || mode == BindingMode.OneWayToSource);

            object current             = sourceObject;
            object previous            = null;
            BindingExpressionPart part = null;

            for (var i = 0; i < _parts.Count; i++)
            {
                part = _parts[i];
                bool isLast = i + 1 == _parts.Count;

                if (!part.IsSelf && current != null)
                {
                    // Allow the object instance itself to provide its own TypeInfo
                    var reflectable = current as IReflectableType;
                    System.Reflection.TypeInfo currentType = reflectable != null?reflectable.GetTypeInfo() : current.GetType().GetTypeInfo();

                    if (part.LastGetter == null || !part.LastGetter.DeclaringType.GetTypeInfo().IsAssignableFrom(currentType))
                    {
                        SetupPart(currentType, part);
                    }

                    if (!isLast)
                    {
                        part.TryGetValue(current, out current);
                    }
                }

                if (!part.IsSelf && current != null)
                {
                    if ((needsGetter && part.LastGetter == null) || (needsSetter && part.NextPart == null && part.LastSetter == null))
                    {
                        Console.WriteLine("Binding, " + PropertyNotFoundErrorMessage, part.Content, current, target.GetType(), property.PropertyName);
                        break;
                    }
                }

                if (mode == BindingMode.OneWay || mode == BindingMode.TwoWay)
                {
                    var inpc = current as INotifyPropertyChanged;
                    if (inpc != null && !ReferenceEquals(current, previous))
                    {
                        part.Subscribe(inpc);
                    }
                }

                previous = current;
            }

            Debug.Assert(part != null, "There should always be at least the self part in the expression.");

            if (needsGetter)
            {
                object value = property.DefaultValue;
                if (part.TryGetValue(current, out value) || part.IsSelf)
                {
                    value = Binding.GetSourceValue(value, property.ReturnType);
                }
                else
                {
                    value = property.DefaultValue;
                }

                if (!TryConvert(ref value, property.ReturnType, true))
                {
                    Console.WriteLine($"Binding : {value} can not be converted to type {property.ReturnType}");
                    return;
                }

                target.SetValueCore(property, value, SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted, false);
            }
            else if (needsSetter && part.LastSetter != null && current != null)
            {
                object value = Binding.GetTargetValue(target.GetValue(property), part.SetterType);

                if (!TryConvert(ref value, part.SetterType, false))
                {
                    Console.WriteLine($"Binding : {value} can not be converted to type {part.SetterType}");
                    return;
                }

                object[] args;
                if (part.IsIndexer)
                {
                    args = new object[part.Arguments.Length + 1];
                    part.Arguments.CopyTo(args, 0);
                    args[args.Length - 1] = value;
                }
                else if (part.IsBindablePropertySetter)
                {
                    args = new[] { part.BindablePropertyField, value };
                }
                else
                {
                    args = new[] { value };
                }

                part.LastSetter.Invoke(current, args);
            }
        }