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() },
110 // more or less the encoding of this, without the need to reflect
111 // http://msdn.microsoft.com/en-us/library/y5b434w4.aspx
112 static readonly Dictionary<Type, Type[]> SimpleConvertTypes = new Dictionary<Type, Type[]>
114 { typeof(sbyte), new[] { typeof(string), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
115 { typeof(byte), new[] { typeof(string), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
116 { typeof(short), new[] { typeof(string), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
117 { typeof(ushort), new[] { typeof(string), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
118 { typeof(int), new[] { typeof(string), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
119 { typeof(uint), new[] { typeof(string), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
120 { typeof(long), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } },
121 { typeof(char), new[] { typeof(string), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
122 { typeof(float), new[] { typeof(string), typeof(double) } },
123 { typeof(ulong), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } }
126 BindableProperty(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
127 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
128 CoerceValueDelegate coerceValue = null, BindablePropertyBindingChanging bindingChanging = null, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null)
130 if (propertyName == null)
131 throw new ArgumentNullException("propertyName");
132 if (ReferenceEquals(returnType, null))
133 throw new ArgumentNullException("returnType");
134 if (ReferenceEquals(declaringType, null))
135 throw new ArgumentNullException("declaringType");
137 // don't use Enum.IsDefined as its redonkulously expensive for what it does
138 if (defaultBindingMode != BindingMode.Default && defaultBindingMode != BindingMode.OneWay && defaultBindingMode != BindingMode.OneWayToSource && defaultBindingMode != BindingMode.TwoWay && defaultBindingMode != BindingMode.OneTime)
139 throw new ArgumentException("Not a valid type of BindingMode", "defaultBindingMode");
140 if (defaultValue == null && Nullable.GetUnderlyingType(returnType) == null && returnType.GetTypeInfo().IsValueType)
141 throw new ArgumentException("Not a valid default value", "defaultValue");
142 if (defaultValue != null && !returnType.IsInstanceOfType(defaultValue))
143 throw new ArgumentException("Default value did not match return type", "defaultValue");
144 if (defaultBindingMode == BindingMode.Default)
145 defaultBindingMode = BindingMode.OneWay;
147 PropertyName = propertyName;
148 ReturnType = returnType;
149 ReturnTypeInfo = returnType.GetTypeInfo();
150 DeclaringType = declaringType;
151 DefaultValue = defaultValue;
152 DefaultBindingMode = defaultBindingMode;
153 PropertyChanged = propertyChanged;
154 PropertyChanging = propertyChanging;
155 ValidateValue = validateValue;
156 CoerceValue = coerceValue;
157 BindingChanging = bindingChanging;
158 IsReadOnly = isReadOnly;
159 DefaultValueCreator = defaultValueCreator;
163 /// Gets the type declaring the BindableProperty.
165 public Type DeclaringType { get; private set; }
168 /// Gets the default BindingMode.
170 public BindingMode DefaultBindingMode { get; private set; }
173 /// Gets the default value for the BindableProperty.
175 public object DefaultValue { get; }
178 /// Gets a value indicating if the BindableProperty is created form a BindablePropertyKey.
180 public bool IsReadOnly { get; private set; }
183 /// Gets the property name.
185 public string PropertyName { get; }
188 /// Gets the type of the BindableProperty.
190 public Type ReturnType { get; }
192 internal BindablePropertyBindingChanging BindingChanging { get; private set; }
194 internal CoerceValueDelegate CoerceValue { get; private set; }
196 internal CreateDefaultValueDelegate DefaultValueCreator { get; }
198 internal BindingPropertyChangedDelegate PropertyChanged { get; private set; }
200 internal BindingPropertyChangingDelegate PropertyChanging { get; private set; }
202 internal System.Reflection.TypeInfo ReturnTypeInfo { get; }
204 internal ValidateValueDelegate ValidateValue { get; private set; }
207 /// Deprecated. Do not use.
209 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
210 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
211 /// <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
212 /// <param name="defaultValue">The default value for the property.</param>
213 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
214 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
215 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
216 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
217 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
218 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
219 /// <returns>A newly created BindableProperty.</returns>
220 [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
221 public static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
222 ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
223 BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
224 CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
226 return Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, defaultValueCreator: defaultValueCreator);
230 /// Creates a new instance of the BindableProperty class.
232 /// <param name="propertyName">The name of the BindableProperty.</param>
233 /// <param name="returnType">The type of the property.</param>
234 /// <param name="declaringType">The type of the declaring object.</param>
235 /// <param name="defaultValue">The default value for the property.</param>
236 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
237 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
238 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
239 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
240 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
241 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
242 /// <returns>A newly created BindableProperty.</returns>
243 public static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue = null, BindingMode defaultBindingMode = BindingMode.OneWay,
244 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
245 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
247 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
248 defaultValueCreator: defaultValueCreator);
252 /// Deprecated. Do not use.
254 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
255 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
256 /// <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
257 /// <param name="defaultValue">The default value for the property.</param>
258 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
259 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
260 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
261 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
262 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
263 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
264 [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
265 public static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
266 BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
267 BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
268 CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
270 return CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null,
271 defaultValueCreator: defaultValueCreator);
275 /// Creates a new instance of the BindableProperty class for an attached property.
277 /// <param name="propertyName">The name of the BindableProperty.</param>
278 /// <param name="returnType">The type of the property.</param>
279 /// <param name="declaringType">The type of the declaring object.</param>
280 /// <param name="defaultValue">The default value for the property.</param>
281 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
282 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
283 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
284 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
285 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
286 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
287 /// <returns>A newly created BindableProperty.</returns>
288 public static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
289 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
290 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
292 return CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, false, defaultValueCreator);
296 /// Deprecated. Do not use.
298 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
299 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
300 /// <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
301 /// <param name="defaultValue">The default value for the property.</param>
302 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
303 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
304 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
305 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
306 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
307 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
308 /// <returns>A newly created attached read-only BindablePropertyKey.</returns>
309 [Obsolete("CreateAttachedReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
310 public static BindablePropertyKey CreateAttachedReadOnly<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
311 BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
312 BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
313 CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
317 new BindablePropertyKey(CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
318 defaultValueCreator));
322 /// Creates a new instance of the BindableProperty class for attached read-only properties.
324 /// <param name="propertyName">The name of the BindableProperty.</param>
325 /// <param name="returnType">The type of the property.</param>
326 /// <param name="declaringType">The type of the declaring object.</param>
327 /// <param name="defaultValue">The default value for the property.</param>
328 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
329 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
330 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
331 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
332 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
333 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
334 /// <returns>A newly created attached read-only BindablePropertyKey.</returns>
335 public static BindablePropertyKey CreateAttachedReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
336 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
337 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
340 new BindablePropertyKey(CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
341 defaultValueCreator));
345 /// Deprecated. Do not use.
347 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
348 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
349 /// <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
350 /// <param name="defaultValue">The default value for the property.</param>
351 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
352 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
353 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
354 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
355 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
356 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
357 /// <returns>A newly created BindablePropertyKey.</returns>
358 [Obsolete("CreateReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
359 public static BindablePropertyKey CreateReadOnly<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue,
360 BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
361 BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
362 CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
364 return new BindablePropertyKey(Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator));
368 /// Creates a new instance of the BindablePropertyKey class.
370 /// <param name="propertyName">The name of the BindableProperty.</param>
371 /// <param name="returnType">The type of the property.</param>
372 /// <param name="declaringType">The type of the declaring object.</param>
373 /// <param name="defaultValue">The default value for the property.</param>
374 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
375 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
376 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
377 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
378 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
379 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
380 /// <returns>A newly created BindablePropertyKey.</returns>
381 public static BindablePropertyKey CreateReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
382 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
383 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
386 new BindablePropertyKey(new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
387 isReadOnly: true, defaultValueCreator: defaultValueCreator));
390 [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
391 internal static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode,
392 ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
393 CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
394 CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
397 throw new ArgumentNullException("getter");
399 Expression expr = getter.Body;
401 var unary = expr as UnaryExpression;
403 expr = unary.Operand;
405 var member = expr as MemberExpression;
407 throw new ArgumentException("getter must be a MemberExpression", "getter");
409 var property = (PropertyInfo)member.Member;
411 ValidateValueDelegate untypedValidateValue = null;
412 BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
413 BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
414 CoerceValueDelegate untypedCoerceValue = null;
415 CreateDefaultValueDelegate untypedDefaultValueCreator = null;
416 if (validateValue != null)
417 untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
418 if (propertyChanged != null)
419 untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
420 if (propertyChanging != null)
421 untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
422 if (coerceValue != null)
423 untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
424 if (defaultValueCreator != null)
425 untypedDefaultValueCreator = o => defaultValueCreator((TDeclarer)o);
427 return new BindableProperty(property.Name, property.PropertyType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged,
428 untypedBindingPropertyChanging, untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
431 internal static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
432 BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
433 CreateDefaultValueDelegate defaultValueCreator = null)
435 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging,
436 defaultValueCreator: defaultValueCreator);
439 [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
440 internal static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode,
441 ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
442 CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
443 CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
445 if (staticgetter == null)
446 throw new ArgumentNullException("staticgetter");
448 Expression expr = staticgetter.Body;
450 var unary = expr as UnaryExpression;
452 expr = unary.Operand;
454 var methodcall = expr as MethodCallExpression;
455 if (methodcall == null)
456 throw new ArgumentException("staticgetter must be a MethodCallExpression", "staticgetter");
458 MethodInfo method = methodcall.Method;
459 if (!method.Name.StartsWith("Get", StringComparison.Ordinal))
460 throw new ArgumentException("staticgetter name must start with Get", "staticgetter");
462 string propertyname = method.Name.Substring(3);
464 ValidateValueDelegate untypedValidateValue = null;
465 BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
466 BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
467 CoerceValueDelegate untypedCoerceValue = null;
468 CreateDefaultValueDelegate untypedDefaultValueCreator = null;
469 if (validateValue != null)
470 untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
471 if (propertyChanged != null)
472 untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
473 if (propertyChanging != null)
474 untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
475 if (coerceValue != null)
476 untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
477 if (defaultValueCreator != null)
478 untypedDefaultValueCreator = o => defaultValueCreator(o);
480 return new BindableProperty(propertyname, method.ReturnType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged, untypedBindingPropertyChanging,
481 untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
484 internal static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
485 BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
486 bool isReadOnly, CreateDefaultValueDelegate defaultValueCreator = null)
488 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging, isReadOnly,
489 defaultValueCreator);
492 internal object GetDefaultValue(BindableObject bindable)
494 if (DefaultValueCreator != null)
495 return DefaultValueCreator(bindable);
500 internal bool TryConvert(ref object value)
504 return !ReturnTypeInfo.IsValueType || ReturnTypeInfo.IsGenericType && ReturnTypeInfo.GetGenericTypeDefinition() == typeof(Nullable<>);
507 Type valueType = value.GetType();
508 Type type = ReturnType;
510 // Dont support arbitrary IConvertible by limiting which types can use this
511 Type[] convertableTo;
512 TypeConverter typeConverterTo;
513 if (SimpleConvertTypes.TryGetValue(valueType, out convertableTo) && Array.IndexOf(convertableTo, type) != -1)
515 value = Convert.ChangeType(value, type);
517 else if (WellKnownConvertTypes.TryGetValue(type, out typeConverterTo) && typeConverterTo.CanConvertFrom(valueType))
519 value = typeConverterTo.ConvertFromInvariantString(value.ToString());
521 else if (!ReturnTypeInfo.IsAssignableFrom(valueType.GetTypeInfo()))
523 var cast = type.GetImplicitConversionOperator(fromType: valueType, toType: type)
524 ?? valueType.GetImplicitConversionOperator(fromType: valueType, toType: type);
529 value = cast.Invoke(null, new[] { value });
535 internal delegate void BindablePropertyBindingChanging(BindableObject bindable, BindingBase oldValue, BindingBase newValue);