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); } }
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); } }
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; } }