2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Linq.Expressions;
5 using System.Reflection;
6 using System.ComponentModel;
7 using Tizen.NUI.Binding.Internals;
10 namespace Tizen.NUI.Binding
13 /// A BindableProperty is a backing store for properties allowing bindings on BindableObject.
15 [DebuggerDisplay("{PropertyName}")]
16 [TypeConverter(typeof(BindablePropertyConverter))]
17 [EditorBrowsable(EditorBrowsableState.Never)]
18 public sealed class BindableProperty
21 /// Delegate for BindableProperty.PropertyChanged.
23 /// <param name="bindable">The bindable object that contains the property.</param>
24 /// <param name="oldValue">The old property value.</param>
25 /// <param name="newValue">The new property value.</param>
26 public delegate void BindingPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue);
29 /// Strongly-typed delegate for BindableProperty.PropertyChanged.
31 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
32 /// <param name="bindable">The bindable object that contains the property.</param>
33 /// <param name="oldValue">The old property value.</param>
34 /// <param name="newValue">The new property value.</param>
35 public delegate void BindingPropertyChangedDelegate<in TPropertyType>(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);
38 /// Delegate for BindableProperty.PropertyChanging.
40 /// <param name="bindable">The bindable object that contains the property.</param>
41 /// <param name="oldValue">The old property value.</param>
42 /// <param name="newValue">The new property value.</param>
43 public delegate void BindingPropertyChangingDelegate(BindableObject bindable, object oldValue, object newValue);
46 /// Strongly-typed delegate for BindableProperty.PropertyChanging.
48 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
49 /// <param name="bindable">The bindable object that contains the property.</param>
50 /// <param name="oldValue">The old property value.</param>
51 /// <param name="newValue">The new property value.</param>
52 public delegate void BindingPropertyChangingDelegate<in TPropertyType>(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);
55 /// Delegate for BindableProperty.CoerceValue.
57 /// <param name="bindable">The bindable object that contains the property.</param>
58 /// <param name="value">The value to coerce.</param>
59 /// <returns>System.Object</returns>
60 public delegate object CoerceValueDelegate(BindableObject bindable, object value);
63 /// Strongly-typed delegate for BindableProperty.CoerceValue.
65 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
66 /// <param name="bindable">The bindable object that contains the property.</param>
67 /// <param name="value">The value to coerce.</param>
68 /// <returns>TPropertyType</returns>
69 public delegate TPropertyType CoerceValueDelegate<TPropertyType>(BindableObject bindable, TPropertyType value);
72 /// Delegate for BindableProperty.DefaultValueCreator.
74 /// <param name="bindable">The bindable object that contains the property.</param>
75 /// <returns>System.Object</returns>
76 public delegate object CreateDefaultValueDelegate(BindableObject bindable);
79 /// Strongly-typed delegate for BindableProperty.DefaultValueCreator.
81 /// <typeparam name="TDeclarer">The type of the object that delared the property.</typeparam>
82 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
83 /// <param name="bindable">The bindable object that contains the property.</param>
84 /// <returns>TPropertyType</returns>
85 public delegate TPropertyType CreateDefaultValueDelegate<in TDeclarer, out TPropertyType>(TDeclarer bindable);
88 /// Delegate for BindableProperty.ValidateValue.
90 /// <param name="bindable">The bindable object that contains the property.</param>
91 /// <param name="value">The default value.</param>
92 /// <returns>System.Boolean</returns>
93 public delegate bool ValidateValueDelegate(BindableObject bindable, object value);
96 /// Strongly-typed delegate for BindableProperty.ValidateValue.
98 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
99 /// <param name="bindable">The bindable object that contains the property.</param>
100 /// <param name="value">The default value.</param>
101 /// <returns>System.Boolean</returns>
102 public delegate bool ValidateValueDelegate<in TPropertyType>(BindableObject bindable, TPropertyType value);
104 static readonly Dictionary<Type, TypeConverter> WellKnownConvertTypes = new Dictionary<Type,TypeConverter>
106 { typeof(Uri), new UriTypeConverter() },
107 { typeof(Color), new ColorTypeConverter() },
108 { typeof(Size2D), new Size2DTypeConverter() },
109 { typeof(Position2D), new Position2DTypeConverter() },
110 { typeof(Size), new SizeTypeConverter() },
111 { typeof(Position), new PositionTypeConverter() },
112 { typeof(Rectangle), new RectangleTypeConverter() },
113 { typeof(Rotation), new RotationTypeConverter() },
114 { typeof(Vector2), new Vector2TypeConverter() },
115 { typeof(Vector3), new Vector3TypeConverter() },
116 { typeof(Vector4), new Vector4TypeConverter() },
117 { typeof(RelativeVector2), new RelativeVector2TypeConverter() },
118 { typeof(RelativeVector3), new RelativeVector3TypeConverter() },
119 { typeof(RelativeVector4), new RelativeVector4TypeConverter() },
122 //Modification for NUI XAML : user defined converter for DynamicResource can be added
123 static internal Dictionary<Type, TypeConverter> UserCustomConvertTypes = new Dictionary<Type, TypeConverter>
127 // more or less the encoding of this, without the need to reflect
128 // http://msdn.microsoft.com/en-us/library/y5b434w4.aspx
129 static readonly Dictionary<Type, Type[]> SimpleConvertTypes = new Dictionary<Type, Type[]>
131 { typeof(sbyte), new[] { typeof(string), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
132 { typeof(byte), new[] { typeof(string), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
133 { typeof(short), new[] { typeof(string), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
134 { typeof(ushort), new[] { typeof(string), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
135 { typeof(int), new[] { typeof(string), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
136 { typeof(uint), new[] { typeof(string), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
137 { typeof(long), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } },
138 { typeof(char), new[] { typeof(string), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
139 { typeof(float), new[] { typeof(string), typeof(double) } },
140 { typeof(ulong), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } }
143 BindableProperty(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
144 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
145 CoerceValueDelegate coerceValue = null, BindablePropertyBindingChanging bindingChanging = null, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null)
147 if (propertyName == null)
148 throw new ArgumentNullException("propertyName");
149 if (ReferenceEquals(returnType, null))
150 throw new ArgumentNullException("returnType");
151 if (ReferenceEquals(declaringType, null))
152 throw new ArgumentNullException("declaringType");
154 // don't use Enum.IsDefined as its redonkulously expensive for what it does
155 if (defaultBindingMode != BindingMode.Default && defaultBindingMode != BindingMode.OneWay && defaultBindingMode != BindingMode.OneWayToSource && defaultBindingMode != BindingMode.TwoWay && defaultBindingMode != BindingMode.OneTime)
156 throw new ArgumentException("Not a valid type of BindingMode", "defaultBindingMode");
157 if (defaultValue == null && Nullable.GetUnderlyingType(returnType) == null && returnType.GetTypeInfo().IsValueType)
158 throw new ArgumentException("Not a valid default value", "defaultValue");
159 if (defaultValue != null && !returnType.IsInstanceOfType(defaultValue))
160 throw new ArgumentException("Default value did not match return type", "defaultValue");
161 if (defaultBindingMode == BindingMode.Default)
162 defaultBindingMode = BindingMode.OneWay;
164 PropertyName = propertyName;
165 ReturnType = returnType;
166 ReturnTypeInfo = returnType.GetTypeInfo();
167 DeclaringType = declaringType;
168 DefaultValue = defaultValue;
169 DefaultBindingMode = defaultBindingMode;
170 PropertyChanged = propertyChanged;
171 PropertyChanging = propertyChanging;
172 ValidateValue = validateValue;
173 CoerceValue = coerceValue;
174 BindingChanging = bindingChanging;
175 IsReadOnly = isReadOnly;
176 DefaultValueCreator = defaultValueCreator;
180 /// Gets the type declaring the BindableProperty.
182 public Type DeclaringType { get; private set; }
185 /// Gets the default BindingMode.
187 public BindingMode DefaultBindingMode { get; private set; }
190 /// Gets the default value for the BindableProperty.
192 public object DefaultValue { get; }
195 /// Gets a value indicating if the BindableProperty is created form a BindablePropertyKey.
197 public bool IsReadOnly { get; private set; }
200 /// Gets the property name.
202 public string PropertyName { get; }
205 /// Gets the type of the BindableProperty.
207 public Type ReturnType { get; }
209 internal BindablePropertyBindingChanging BindingChanging { get; private set; }
211 internal CoerceValueDelegate CoerceValue { get; private set; }
213 internal CreateDefaultValueDelegate DefaultValueCreator { get; }
215 internal BindingPropertyChangedDelegate PropertyChanged { get; private set; }
217 internal BindingPropertyChangingDelegate PropertyChanging { get; private set; }
219 internal System.Reflection.TypeInfo ReturnTypeInfo { get; }
221 internal ValidateValueDelegate ValidateValue { get; private set; }
224 /// Deprecated. Do not use.
226 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
227 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
228 /// <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
229 /// <param name="defaultValue">The default value for the property.</param>
230 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
231 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
232 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
233 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
234 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
235 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
236 /// <returns>A newly created BindableProperty.</returns>
237 [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
238 public static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
239 ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
240 BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
241 CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
243 return Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, defaultValueCreator: defaultValueCreator);
247 /// Creates a new instance of the BindableProperty class.
249 /// <param name="propertyName">The name of the BindableProperty.</param>
250 /// <param name="returnType">The type of the property.</param>
251 /// <param name="declaringType">The type of the declaring object.</param>
252 /// <param name="defaultValue">The default value for the property.</param>
253 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
254 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
255 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
256 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
257 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
258 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
259 /// <returns>A newly created BindableProperty.</returns>
260 public static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue = null, BindingMode defaultBindingMode = BindingMode.OneWay,
261 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
262 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
264 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
265 defaultValueCreator: defaultValueCreator);
269 /// Deprecated. Do not use.
271 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
272 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
273 /// <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
274 /// <param name="defaultValue">The default value for the property.</param>
275 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
276 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
277 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
278 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
279 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
280 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
281 [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
282 public static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
283 BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
284 BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
285 CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
287 return CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null,
288 defaultValueCreator: defaultValueCreator);
292 /// Creates a new instance of the BindableProperty class for an attached property.
294 /// <param name="propertyName">The name of the BindableProperty.</param>
295 /// <param name="returnType">The type of the property.</param>
296 /// <param name="declaringType">The type of the declaring object.</param>
297 /// <param name="defaultValue">The default value for the property.</param>
298 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
299 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
300 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
301 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
302 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
303 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
304 /// <returns>A newly created BindableProperty.</returns>
305 public static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
306 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
307 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
309 return CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, false, defaultValueCreator);
313 /// Deprecated. Do not use.
315 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
316 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
317 /// <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
318 /// <param name="defaultValue">The default value for the property.</param>
319 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
320 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
321 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
322 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
323 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
324 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
325 /// <returns>A newly created attached read-only BindablePropertyKey.</returns>
326 [Obsolete("CreateAttachedReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
327 public static BindablePropertyKey CreateAttachedReadOnly<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
328 BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
329 BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
330 CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
334 new BindablePropertyKey(CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
335 defaultValueCreator));
339 /// Creates a new instance of the BindableProperty class for attached read-only properties.
341 /// <param name="propertyName">The name of the BindableProperty.</param>
342 /// <param name="returnType">The type of the property.</param>
343 /// <param name="declaringType">The type of the declaring object.</param>
344 /// <param name="defaultValue">The default value for the property.</param>
345 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
346 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
347 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
348 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
349 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
350 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
351 /// <returns>A newly created attached read-only BindablePropertyKey.</returns>
352 public static BindablePropertyKey CreateAttachedReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
353 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
354 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
357 new BindablePropertyKey(CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
358 defaultValueCreator));
362 /// Deprecated. Do not use.
364 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
365 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
366 /// <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
367 /// <param name="defaultValue">The default value for the property.</param>
368 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
369 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
370 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
371 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
372 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
373 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
374 /// <returns>A newly created BindablePropertyKey.</returns>
375 [Obsolete("CreateReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
376 public static BindablePropertyKey CreateReadOnly<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue,
377 BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
378 BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
379 CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
381 return new BindablePropertyKey(Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator));
385 /// Creates a new instance of the BindablePropertyKey class.
387 /// <param name="propertyName">The name of the BindableProperty.</param>
388 /// <param name="returnType">The type of the property.</param>
389 /// <param name="declaringType">The type of the declaring object.</param>
390 /// <param name="defaultValue">The default value for the property.</param>
391 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
392 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
393 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
394 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
395 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
396 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
397 /// <returns>A newly created BindablePropertyKey.</returns>
398 public static BindablePropertyKey CreateReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
399 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
400 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
403 new BindablePropertyKey(new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
404 isReadOnly: true, defaultValueCreator: defaultValueCreator));
407 [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
408 internal static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode,
409 ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
410 CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
411 CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
414 throw new ArgumentNullException("getter");
416 Expression expr = getter.Body;
418 var unary = expr as UnaryExpression;
420 expr = unary.Operand;
422 var member = expr as MemberExpression;
424 throw new ArgumentException("getter must be a MemberExpression", "getter");
426 var property = (PropertyInfo)member.Member;
428 ValidateValueDelegate untypedValidateValue = null;
429 BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
430 BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
431 CoerceValueDelegate untypedCoerceValue = null;
432 CreateDefaultValueDelegate untypedDefaultValueCreator = null;
433 if (validateValue != null)
434 untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
435 if (propertyChanged != null)
436 untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
437 if (propertyChanging != null)
438 untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
439 if (coerceValue != null)
440 untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
441 if (defaultValueCreator != null)
442 untypedDefaultValueCreator = o => defaultValueCreator((TDeclarer)o);
444 return new BindableProperty(property.Name, property.PropertyType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged,
445 untypedBindingPropertyChanging, untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
448 internal static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
449 BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
450 CreateDefaultValueDelegate defaultValueCreator = null)
452 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging,
453 defaultValueCreator: defaultValueCreator);
456 [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
457 internal static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode,
458 ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
459 CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
460 CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
462 if (staticgetter == null)
463 throw new ArgumentNullException("staticgetter");
465 Expression expr = staticgetter.Body;
467 var unary = expr as UnaryExpression;
469 expr = unary.Operand;
471 var methodcall = expr as MethodCallExpression;
472 if (methodcall == null)
473 throw new ArgumentException("staticgetter must be a MethodCallExpression", "staticgetter");
475 MethodInfo method = methodcall.Method;
476 if (!method.Name.StartsWith("Get", StringComparison.Ordinal))
477 throw new ArgumentException("staticgetter name must start with Get", "staticgetter");
479 string propertyname = method.Name.Substring(3);
481 ValidateValueDelegate untypedValidateValue = null;
482 BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
483 BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
484 CoerceValueDelegate untypedCoerceValue = null;
485 CreateDefaultValueDelegate untypedDefaultValueCreator = null;
486 if (validateValue != null)
487 untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
488 if (propertyChanged != null)
489 untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
490 if (propertyChanging != null)
491 untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
492 if (coerceValue != null)
493 untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
494 if (defaultValueCreator != null)
495 untypedDefaultValueCreator = o => defaultValueCreator(o);
497 return new BindableProperty(propertyname, method.ReturnType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged, untypedBindingPropertyChanging,
498 untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
501 internal static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
502 BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
503 bool isReadOnly, CreateDefaultValueDelegate defaultValueCreator = null)
505 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging, isReadOnly,
506 defaultValueCreator);
509 internal object GetDefaultValue(BindableObject bindable)
511 if (DefaultValueCreator != null)
512 return DefaultValueCreator(bindable);
517 internal bool TryConvert(ref object value)
521 return !ReturnTypeInfo.IsValueType || ReturnTypeInfo.IsGenericType && ReturnTypeInfo.GetGenericTypeDefinition() == typeof(Nullable<>);
524 Type valueType = value.GetType();
525 Type type = ReturnType;
527 // Dont support arbitrary IConvertible by limiting which types can use this
528 Type[] convertableTo;
529 TypeConverter typeConverterTo;
530 if (SimpleConvertTypes.TryGetValue(valueType, out convertableTo) && Array.IndexOf(convertableTo, type) != -1)
532 value = Convert.ChangeType(value, type);
534 else if (WellKnownConvertTypes.TryGetValue(type, out typeConverterTo) && typeConverterTo.CanConvertFrom(valueType))
536 value = typeConverterTo.ConvertFromInvariantString(value.ToString());
538 else if (UserCustomConvertTypes.TryGetValue(type, out typeConverterTo) && typeConverterTo.CanConvertFrom(valueType))
540 //Modification for NUI XAML : user defined converter for DynamicResource can be added
541 value = typeConverterTo.ConvertFromInvariantString(value.ToString());
543 else if (!ReturnTypeInfo.IsAssignableFrom(valueType.GetTypeInfo()))
545 var cast = type.GetImplicitConversionOperator(fromType: valueType, toType: type)
546 ?? valueType.GetImplicitConversionOperator(fromType: valueType, toType: type);
551 value = cast.Invoke(null, new[] { value });
557 internal delegate void BindablePropertyBindingChanging(BindableObject bindable, BindingBase oldValue, BindingBase newValue);