using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; using System.ComponentModel; using Tizen.NUI.Binding.Internals; using Tizen.NUI.Xaml; namespace Tizen.NUI.Binding { /// /// A BindableProperty is a backing store for properties allowing bindings on BindableObject. /// [DebuggerDisplay("{PropertyName}")] [TypeConverter(typeof(BindablePropertyConverter))] [EditorBrowsable(EditorBrowsableState.Never)] public sealed class BindableProperty { /// /// Delegate for BindableProperty.PropertyChanged. /// /// The bindable object that contains the property. /// The old property value. /// The new property value. public delegate void BindingPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue); /// /// Strongly-typed delegate for BindableProperty.PropertyChanged. /// /// The type of the bound property. /// The bindable object that contains the property. /// The old property value. /// The new property value. public delegate void BindingPropertyChangedDelegate(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue); /// /// Delegate for BindableProperty.PropertyChanging. /// /// The bindable object that contains the property. /// The old property value. /// The new property value. public delegate void BindingPropertyChangingDelegate(BindableObject bindable, object oldValue, object newValue); /// /// Strongly-typed delegate for BindableProperty.PropertyChanging. /// /// The type of the bound property. /// The bindable object that contains the property. /// The old property value. /// The new property value. public delegate void BindingPropertyChangingDelegate(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue); /// /// Delegate for BindableProperty.CoerceValue. /// /// The bindable object that contains the property. /// The value to coerce. /// System.Object public delegate object CoerceValueDelegate(BindableObject bindable, object value); /// /// Strongly-typed delegate for BindableProperty.CoerceValue. /// /// The type of the bound property. /// The bindable object that contains the property. /// The value to coerce. /// TPropertyType public delegate TPropertyType CoerceValueDelegate(BindableObject bindable, TPropertyType value); /// /// Delegate for BindableProperty.DefaultValueCreator. /// /// The bindable object that contains the property. /// System.Object public delegate object CreateDefaultValueDelegate(BindableObject bindable); /// /// Strongly-typed delegate for BindableProperty.DefaultValueCreator. /// /// The type of the object that delared the property. /// The type of the bound property. /// The bindable object that contains the property. /// TPropertyType public delegate TPropertyType CreateDefaultValueDelegate(TDeclarer bindable); /// /// Delegate for BindableProperty.ValidateValue. /// /// The bindable object that contains the property. /// The default value. /// System.Boolean public delegate bool ValidateValueDelegate(BindableObject bindable, object value); /// /// Strongly-typed delegate for BindableProperty.ValidateValue. /// /// The type of the bound property. /// The bindable object that contains the property. /// The default value. /// System.Boolean public delegate bool ValidateValueDelegate(BindableObject bindable, TPropertyType value); static readonly Dictionary WellKnownConvertTypes = new Dictionary { { typeof(Uri), new UriTypeConverter() }, { typeof(Color), new ColorTypeConverter() }, }; // more or less the encoding of this, without the need to reflect // http://msdn.microsoft.com/en-us/library/y5b434w4.aspx static readonly Dictionary SimpleConvertTypes = new Dictionary { { typeof(sbyte), new[] { typeof(string), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } }, { typeof(byte), new[] { typeof(string), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } }, { typeof(short), new[] { typeof(string), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } }, { typeof(ushort), new[] { typeof(string), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } }, { typeof(int), new[] { typeof(string), typeof(long), typeof(float), typeof(double), typeof(decimal) } }, { typeof(uint), new[] { typeof(string), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } }, { typeof(long), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } }, { typeof(char), new[] { typeof(string), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } }, { typeof(float), new[] { typeof(string), typeof(double) } }, { typeof(ulong), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } } }; BindableProperty(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, BindablePropertyBindingChanging bindingChanging = null, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null) { if (propertyName == null) throw new ArgumentNullException("propertyName"); if (ReferenceEquals(returnType, null)) throw new ArgumentNullException("returnType"); if (ReferenceEquals(declaringType, null)) throw new ArgumentNullException("declaringType"); // don't use Enum.IsDefined as its redonkulously expensive for what it does if (defaultBindingMode != BindingMode.Default && defaultBindingMode != BindingMode.OneWay && defaultBindingMode != BindingMode.OneWayToSource && defaultBindingMode != BindingMode.TwoWay && defaultBindingMode != BindingMode.OneTime) throw new ArgumentException("Not a valid type of BindingMode", "defaultBindingMode"); if (defaultValue == null && Nullable.GetUnderlyingType(returnType) == null && returnType.GetTypeInfo().IsValueType) throw new ArgumentException("Not a valid default value", "defaultValue"); if (defaultValue != null && !returnType.IsInstanceOfType(defaultValue)) throw new ArgumentException("Default value did not match return type", "defaultValue"); if (defaultBindingMode == BindingMode.Default) defaultBindingMode = BindingMode.OneWay; PropertyName = propertyName; ReturnType = returnType; ReturnTypeInfo = returnType.GetTypeInfo(); DeclaringType = declaringType; DefaultValue = defaultValue; DefaultBindingMode = defaultBindingMode; PropertyChanged = propertyChanged; PropertyChanging = propertyChanging; ValidateValue = validateValue; CoerceValue = coerceValue; BindingChanging = bindingChanging; IsReadOnly = isReadOnly; DefaultValueCreator = defaultValueCreator; } /// /// Gets the type declaring the BindableProperty. /// public Type DeclaringType { get; private set; } /// /// Gets the default BindingMode. /// public BindingMode DefaultBindingMode { get; private set; } /// /// Gets the default value for the BindableProperty. /// public object DefaultValue { get; } /// /// Gets a value indicating if the BindableProperty is created form a BindablePropertyKey. /// public bool IsReadOnly { get; private set; } /// /// Gets the property name. /// public string PropertyName { get; } /// /// Gets the type of the BindableProperty. /// public Type ReturnType { get; } internal BindablePropertyBindingChanging BindingChanging { get; private set; } internal CoerceValueDelegate CoerceValue { get; private set; } internal CreateDefaultValueDelegate DefaultValueCreator { get; } internal BindingPropertyChangedDelegate PropertyChanged { get; private set; } internal BindingPropertyChangingDelegate PropertyChanging { get; private set; } internal System.Reflection.TypeInfo ReturnTypeInfo { get; } internal ValidateValueDelegate ValidateValue { get; private set; } /// /// Deprecated. Do not use. /// /// The type of the declaring object. /// The type of the property. /// An expression identifying the getter for the property using this BindableProperty as backing store. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created BindableProperty. [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")] public static BindableProperty Create(Expression> getter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) where TDeclarer : BindableObject { return Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, defaultValueCreator: defaultValueCreator); } /// /// Creates a new instance of the BindableProperty class. /// /// The name of the BindableProperty. /// The type of the property. /// The type of the declaring object. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created BindableProperty. public static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue = null, BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) { return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, defaultValueCreator: defaultValueCreator); } /// /// Deprecated. Do not use. /// /// The type of the declaring object. /// The type of the property. /// An expression identifying a static method returning the value of the property using this BindableProperty as backing store. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")] public static BindableProperty CreateAttached(Expression> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) { return CreateAttached(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, defaultValueCreator: defaultValueCreator); } /// /// Creates a new instance of the BindableProperty class for an attached property. /// /// The name of the BindableProperty. /// The type of the property. /// The type of the declaring object. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created BindableProperty. public static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) { return CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, false, defaultValueCreator); } /// /// Deprecated. Do not use. /// /// The type of the declaring object. /// The type of the property. /// An expression identifying a static method returning the value of the property using this BindableProperty as backing store. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created attached read-only BindablePropertyKey. [Obsolete("CreateAttachedReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")] public static BindablePropertyKey CreateAttachedReadOnly(Expression> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) { return new BindablePropertyKey(CreateAttached(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator)); } /// /// Creates a new instance of the BindableProperty class for attached read-only properties. /// /// The name of the BindableProperty. /// The type of the property. /// The type of the declaring object. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created attached read-only BindablePropertyKey. public static BindablePropertyKey CreateAttachedReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) { return new BindablePropertyKey(CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator)); } /// /// Deprecated. Do not use. /// /// The type of the declaring object. /// The type of the property. /// An expression identifying the getter for the property using this BindableProperty as backing store. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created BindablePropertyKey. [Obsolete("CreateReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")] public static BindablePropertyKey CreateReadOnly(Expression> getter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) where TDeclarer : BindableObject { return new BindablePropertyKey(Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator)); } /// /// Creates a new instance of the BindablePropertyKey class. /// /// The name of the BindableProperty. /// The type of the property. /// The type of the declaring object. /// The default value for the property. /// The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay. /// A delegate to be run when a value is set. This parameter is optional. Default is null. /// A delegate to be run when the value has changed. This parameter is optional. Default is null. /// A delegate to be run when the value will change. This parameter is optional. Default is null. /// A delegate used to coerce the range of a value. This parameter is optional. Default is null. /// A Func used to initialize default value for reference types. /// A newly created BindablePropertyKey. public static BindablePropertyKey CreateReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null, CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null) { return new BindablePropertyKey(new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, isReadOnly: true, defaultValueCreator: defaultValueCreator)); } [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")] internal static BindableProperty Create(Expression> getter, TPropertyType defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue, BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null) where TDeclarer : BindableObject { if (getter == null) throw new ArgumentNullException("getter"); Expression expr = getter.Body; var unary = expr as UnaryExpression; if (unary != null) expr = unary.Operand; var member = expr as MemberExpression; if (member == null) throw new ArgumentException("getter must be a MemberExpression", "getter"); var property = (PropertyInfo)member.Member; ValidateValueDelegate untypedValidateValue = null; BindingPropertyChangedDelegate untypedBindingPropertyChanged = null; BindingPropertyChangingDelegate untypedBindingPropertyChanging = null; CoerceValueDelegate untypedCoerceValue = null; CreateDefaultValueDelegate untypedDefaultValueCreator = null; if (validateValue != null) untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value); if (propertyChanged != null) untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue); if (propertyChanging != null) untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue); if (coerceValue != null) untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value); if (defaultValueCreator != null) untypedDefaultValueCreator = o => defaultValueCreator((TDeclarer)o); return new BindableProperty(property.Name, property.PropertyType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged, untypedBindingPropertyChanging, untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator); } internal static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue, BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging, CreateDefaultValueDelegate defaultValueCreator = null) { return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging, defaultValueCreator: defaultValueCreator); } [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")] internal static BindableProperty CreateAttached(Expression> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue, BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null) { if (staticgetter == null) throw new ArgumentNullException("staticgetter"); Expression expr = staticgetter.Body; var unary = expr as UnaryExpression; if (unary != null) expr = unary.Operand; var methodcall = expr as MethodCallExpression; if (methodcall == null) throw new ArgumentException("staticgetter must be a MethodCallExpression", "staticgetter"); MethodInfo method = methodcall.Method; if (!method.Name.StartsWith("Get", StringComparison.Ordinal)) throw new ArgumentException("staticgetter name must start with Get", "staticgetter"); string propertyname = method.Name.Substring(3); ValidateValueDelegate untypedValidateValue = null; BindingPropertyChangedDelegate untypedBindingPropertyChanged = null; BindingPropertyChangingDelegate untypedBindingPropertyChanging = null; CoerceValueDelegate untypedCoerceValue = null; CreateDefaultValueDelegate untypedDefaultValueCreator = null; if (validateValue != null) untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value); if (propertyChanged != null) untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue); if (propertyChanging != null) untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue); if (coerceValue != null) untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value); if (defaultValueCreator != null) untypedDefaultValueCreator = o => defaultValueCreator(o); return new BindableProperty(propertyname, method.ReturnType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged, untypedBindingPropertyChanging, untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator); } internal static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue, BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly, CreateDefaultValueDelegate defaultValueCreator = null) { return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging, isReadOnly, defaultValueCreator); } internal object GetDefaultValue(BindableObject bindable) { if (DefaultValueCreator != null) return DefaultValueCreator(bindable); return DefaultValue; } internal bool TryConvert(ref object value) { if (value == null) { return !ReturnTypeInfo.IsValueType || ReturnTypeInfo.IsGenericType && ReturnTypeInfo.GetGenericTypeDefinition() == typeof(Nullable<>); } Type valueType = value.GetType(); Type type = ReturnType; // Dont support arbitrary IConvertible by limiting which types can use this Type[] convertableTo; TypeConverter typeConverterTo; if (SimpleConvertTypes.TryGetValue(valueType, out convertableTo) && Array.IndexOf(convertableTo, type) != -1) { value = Convert.ChangeType(value, type); } else if (WellKnownConvertTypes.TryGetValue(type, out typeConverterTo) && typeConverterTo.CanConvertFrom(valueType)) { value = typeConverterTo.ConvertFromInvariantString(value.ToString()); } else if (!ReturnTypeInfo.IsAssignableFrom(valueType.GetTypeInfo())) { var cast = type.GetImplicitConversionOperator(fromType: valueType, toType: type) ?? valueType.GetImplicitConversionOperator(fromType: valueType, toType: type); if (cast == null) return false; value = cast.Invoke(null, new[] { value }); } return true; } internal delegate void BindablePropertyBindingChanging(BindableObject bindable, BindingBase oldValue, BindingBase newValue); } }