Example #1
0
        bool TryConvert(BindingExpressionPart part, ref object value, Type convertTo, bool toTarget)
        {
            if (value == null)
            {
                return(true);
            }
            if ((toTarget && _targetProperty.TryConvert(ref value)) || (!toTarget && convertTo.IsInstanceOfType(value)))
            {
                return(true);
            }

            object original = value;

            try
            {
                var stringValue = value as string ?? string.Empty;
                // see: https://bugzilla.xamarin.com/show_bug.cgi?id=32871
                // do not canonicalize "*.[.]"; "1." should not update bound BindableProperty
                if (stringValue.EndsWith(".", StringComparison.Ordinal) && DecimalTypes.Contains(convertTo))
                {
                    value = original;
                    return(false);
                }

                // do not canonicalize "-0"; user will likely enter a period after "-0"
                if (stringValue == "-0" && DecimalTypes.Contains(convertTo))
                {
                    value = original;
                    return(false);
                }

                value = Convert.ChangeType(value, convertTo, CultureInfo.InvariantCulture);
                return(true);
            }
            catch (InvalidCastException)
            {
                value = original;
                return(false);
            }
            catch (FormatException)
            {
                value = original;
                return(false);
            }
            catch (OverflowException)
            {
                value = original;
                return(false);
            }
        }
Example #2
0
        internal static bool TryConvert(ref object value, BindableProperty targetProperty, Type convertTo, bool toTarget)
        {
            if (value == null)
            {
                return(!convertTo.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(convertTo) != null);
            }
            try
            {
                if ((toTarget && targetProperty.TryConvert(ref value)) || (!toTarget && convertTo.IsInstanceOfType(value)))
                {
                    return(true);
                }
            }
            catch (InvalidOperationException)
            {             //that's what TypeConverters ususally throw
                return(false);
            }

            object original = value;

            try
            {
                var stringValue = value as string ?? string.Empty;
                // see: https://bugzilla.xamarin.com/show_bug.cgi?id=32871
                // do not canonicalize "*.[.]"; "1." should not update bound BindableProperty
                if (stringValue.EndsWith(".", StringComparison.Ordinal) && DecimalTypes.Contains(convertTo))
                {
                    value = original;
                    return(false);
                }

                // do not canonicalize "-0"; user will likely enter a period after "-0"
                if (stringValue == "-0" && DecimalTypes.Contains(convertTo))
                {
                    value = original;
                    return(false);
                }

                convertTo = Nullable.GetUnderlyingType(convertTo) ?? convertTo;

                value = Convert.ChangeType(value, convertTo, CultureInfo.InvariantCulture);
                return(true);
            }
            catch (Exception ex) when(ex is InvalidCastException || ex is FormatException || ex is InvalidOperationException || ex is OverflowException)
            {
                value = original;
                return(false);
            }
        }
Example #3
0
        internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
        {
            bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
            bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
            bool silent      = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
            bool fromStyle   = (privateAttributes & SetValuePrivateFlags.FromStyle) != 0;
            bool converted   = (privateAttributes & SetValuePrivateFlags.Converted) != 0;

            if (property == null)
            {
                throw new ArgumentNullException("property");
            }
            if (checkAccess && property.IsReadOnly)
            {
                Debug.WriteLine("Can not set the BindableProperty \"{0}\" because it is readonly.", property.PropertyName);
                return;
            }

            if (!converted && !property.TryConvert(ref value))
            {
                Log.Warning("SetValue", "Can not convert {0} to type '{1}'", value, property.ReturnType);
                return;
            }

            if (property.ValidateValue != null && !property.ValidateValue(this, value))
            {
                throw new ArgumentException("Value was an invalid value for " + property.PropertyName, "value");
            }

            if (property.CoerceValue != null)
            {
                value = property.CoerceValue(this, value);
            }

            BindablePropertyContext context = GetOrCreateContext(property);

            if (manuallySet)
            {
                context.Attributes |= BindableContextAttributes.IsManuallySet;
                context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
            }
            else
            {
                context.Attributes &= ~BindableContextAttributes.IsManuallySet;
            }

            if (fromStyle)
            {
                context.Attributes |= BindableContextAttributes.IsSetFromStyle;
            }
            // else omitted on purpose

            bool currentlyApplying = _applying;

            if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
            {
                Queue <SetValueArgs> delayQueue = context.DelayedSetters;
                if (delayQueue == null)
                {
                    context.DelayedSetters = delayQueue = new Queue <SetValueArgs>();
                }

                delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
            }
            else
            {
                context.Attributes |= BindableContextAttributes.IsBeingSet;
                SetValueActual(property, context, value, currentlyApplying, attributes, silent);

                Queue <SetValueArgs> delayQueue = context.DelayedSetters;
                if (delayQueue != null)
                {
                    while (delayQueue.Count > 0)
                    {
                        SetValueArgs s = delayQueue.Dequeue();
                        SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, s.Attributes);
                    }

                    context.DelayedSetters = null;
                }

                context.Attributes &= ~BindableContextAttributes.IsBeingSet;
            }
        }