2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Generic;
20 using System.Diagnostics;
21 using System.Linq.Expressions;
22 using System.Reflection;
23 using System.ComponentModel;
24 using Tizen.NUI.Binding.Internals;
27 namespace Tizen.NUI.Binding
30 /// A BindableProperty is a backing store for properties allowing bindings on BindableObject.
32 [DebuggerDisplay("{PropertyName}")]
33 [TypeConverter(typeof(BindablePropertyConverter))]
34 [EditorBrowsable(EditorBrowsableState.Never)]
35 public sealed class BindableProperty
38 /// Delegate for BindableProperty.PropertyChanged.
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 BindingPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue);
46 /// Strongly-typed delegate for BindableProperty.PropertyChanged.
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 BindingPropertyChangedDelegate<in TPropertyType>(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);
55 /// Delegate for BindableProperty.PropertyChanging.
57 /// <param name="bindable">The bindable object that contains the property.</param>
58 /// <param name="oldValue">The old property value.</param>
59 /// <param name="newValue">The new property value.</param>
60 public delegate void BindingPropertyChangingDelegate(BindableObject bindable, object oldValue, object newValue);
63 /// Strongly-typed delegate for BindableProperty.PropertyChanging.
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="oldValue">The old property value.</param>
68 /// <param name="newValue">The new property value.</param>
69 public delegate void BindingPropertyChangingDelegate<in TPropertyType>(BindableObject bindable, TPropertyType oldValue, TPropertyType newValue);
72 /// Delegate for BindableProperty.CoerceValue.
74 /// <param name="bindable">The bindable object that contains the property.</param>
75 /// <param name="value">The value to coerce.</param>
76 /// <returns>System.Object</returns>
77 public delegate object CoerceValueDelegate(BindableObject bindable, object value);
80 /// Strongly-typed delegate for BindableProperty.CoerceValue.
82 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
83 /// <param name="bindable">The bindable object that contains the property.</param>
84 /// <param name="value">The value to coerce.</param>
85 /// <returns>TPropertyType</returns>
86 public delegate TPropertyType CoerceValueDelegate<TPropertyType>(BindableObject bindable, TPropertyType value);
89 /// Delegate for BindableProperty.DefaultValueCreator.
91 /// <param name="bindable">The bindable object that contains the property.</param>
92 /// <returns>System.Object</returns>
93 public delegate object CreateDefaultValueDelegate(BindableObject bindable);
96 /// Strongly-typed delegate for BindableProperty.DefaultValueCreator.
98 /// <typeparam name="TDeclarer">The type of the object that delared the property.</typeparam>
99 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
100 /// <param name="bindable">The bindable object that contains the property.</param>
101 /// <returns>TPropertyType</returns>
102 public delegate TPropertyType CreateDefaultValueDelegate<in TDeclarer, out TPropertyType>(TDeclarer bindable);
105 /// Delegate for BindableProperty.ValidateValue.
107 /// <param name="bindable">The bindable object that contains the property.</param>
108 /// <param name="value">The default value.</param>
109 /// <returns>System.Boolean</returns>
110 public delegate bool ValidateValueDelegate(BindableObject bindable, object value);
113 /// Strongly-typed delegate for BindableProperty.ValidateValue.
115 /// <typeparam name="TPropertyType">The type of the bound property.</typeparam>
116 /// <param name="bindable">The bindable object that contains the property.</param>
117 /// <param name="value">The default value.</param>
118 /// <returns>System.Boolean</returns>
119 public delegate bool ValidateValueDelegate<in TPropertyType>(BindableObject bindable, TPropertyType value);
121 //To confirm the static dictionary will be created before the constructor is called.
122 static BindableProperty()
126 static readonly Dictionary<Type, TypeConverter> WellKnownConvertTypes = new Dictionary<Type, TypeConverter>
128 { typeof(Uri), new UriTypeConverter() },
129 { typeof(Color), new ColorTypeConverter() },
130 { typeof(Size2D), new Size2DTypeConverter() },
131 { typeof(Position2D), new Position2DTypeConverter() },
132 { typeof(Size), new SizeTypeConverter() },
133 { typeof(Position), new PositionTypeConverter() },
134 { typeof(Rectangle), new RectangleTypeConverter() },
135 { typeof(Rotation), new RotationTypeConverter() },
136 { typeof(Vector2), new Vector2TypeConverter() },
137 { typeof(Vector3), new Vector3TypeConverter() },
138 { typeof(Vector4), new Vector4TypeConverter() },
139 { typeof(RelativeVector2), new RelativeVector2TypeConverter() },
140 { typeof(RelativeVector3), new RelativeVector3TypeConverter() },
141 { typeof(RelativeVector4), new RelativeVector4TypeConverter() },
144 //Modification for NUI XAML : user defined converter for DynamicResource can be added
145 static internal Dictionary<Type, TypeConverter> UserCustomConvertTypes = new Dictionary<Type, TypeConverter>
149 // more or less the encoding of this, without the need to reflect
150 // http://msdn.microsoft.com/en-us/library/y5b434w4.aspx
151 static readonly Dictionary<Type, Type[]> SimpleConvertTypes = new Dictionary<Type, Type[]>
153 { typeof(sbyte), new[] { typeof(string), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
154 { typeof(byte), new[] { typeof(string), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
155 { typeof(short), new[] { typeof(string), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
156 { typeof(ushort), new[] { typeof(string), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
157 { typeof(int), new[] { typeof(string), typeof(long), typeof(float), typeof(double), typeof(decimal) } },
158 { typeof(uint), new[] { typeof(string), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
159 { typeof(long), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } },
160 { typeof(char), new[] { typeof(string), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) } },
161 { typeof(float), new[] { typeof(string), typeof(double) } },
162 { typeof(ulong), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } }
165 BindableProperty(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
166 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
167 CoerceValueDelegate coerceValue = null, BindablePropertyBindingChanging bindingChanging = null, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null)
169 if (propertyName == null)
170 throw new ArgumentNullException(nameof(propertyName));
171 if (ReferenceEquals(returnType, null))
172 throw new ArgumentNullException(nameof(returnType));
173 if (ReferenceEquals(declaringType, null))
174 throw new ArgumentNullException(nameof(declaringType));
176 // don't use Enum.IsDefined as its redonkulously expensive for what it does
177 if (defaultBindingMode != BindingMode.Default && defaultBindingMode != BindingMode.OneWay && defaultBindingMode != BindingMode.OneWayToSource && defaultBindingMode != BindingMode.TwoWay && defaultBindingMode != BindingMode.OneTime)
178 throw new ArgumentException("Not a valid type of BindingMode", nameof(defaultBindingMode));
179 if (defaultValue == null && Nullable.GetUnderlyingType(returnType) == null && returnType.GetTypeInfo().IsValueType)
180 throw new ArgumentException("Not a valid default value", nameof(defaultValue));
181 if (defaultValue != null && !returnType.IsInstanceOfType(defaultValue))
182 throw new ArgumentException("Default value did not match return type", nameof(defaultValue));
183 if (defaultBindingMode == BindingMode.Default)
184 defaultBindingMode = BindingMode.OneWay;
186 PropertyName = propertyName;
187 ReturnType = returnType;
188 ReturnTypeInfo = returnType.GetTypeInfo();
189 DeclaringType = declaringType;
190 DefaultValue = defaultValue;
191 DefaultBindingMode = defaultBindingMode;
192 PropertyChanged = propertyChanged;
193 PropertyChanging = propertyChanging;
194 ValidateValue = validateValue;
195 CoerceValue = coerceValue;
196 BindingChanging = bindingChanging;
197 IsReadOnly = isReadOnly;
198 DefaultValueCreator = defaultValueCreator;
200 Dictionary<string, BindableProperty> nameToBindableProperty;
201 bindablePropertyOfType.TryGetValue(declaringType, out nameToBindableProperty);
202 if (null == nameToBindableProperty)
204 nameToBindableProperty = new Dictionary<string, BindableProperty>();
205 bindablePropertyOfType.Add(declaringType, nameToBindableProperty);
208 if (!nameToBindableProperty.ContainsKey(propertyName))
210 nameToBindableProperty.Add(propertyName, this);
214 nameToBindableProperty[propertyName] = this;
218 private static bool AddParentTypeProperty(Type type, Dictionary<string, BindableProperty> propertyDict)
224 Dictionary<string, BindableProperty> nameToBindableProperty;
225 bindablePropertyOfType.TryGetValue(type, out nameToBindableProperty);
227 if (null != nameToBindableProperty)
231 foreach (KeyValuePair<string, BindableProperty> keyValuePair in nameToBindableProperty)
233 if (!propertyDict.ContainsKey(keyValuePair.Key))
235 propertyDict.Add(keyValuePair.Key, keyValuePair.Value);
240 if (true == AddParentTypeProperty(type.BaseType, propertyDict))
249 static internal Dictionary<Type, Dictionary<string, BindableProperty>> bindablePropertyOfType = new Dictionary<Type, Dictionary<string, BindableProperty>>();
250 static private HashSet<Type> baseTypePropertyHasBeenAdded = new HashSet<Type>();
252 static internal void GetBindablePropertysOfType(Type type, out Dictionary<string, BindableProperty> dictionary)
256 bindablePropertyOfType.TryGetValue(type, out dictionary);
258 if (!baseTypePropertyHasBeenAdded.Contains(type))
260 bool isCurDictNull = false;
262 if (null == dictionary)
264 isCurDictNull = true;
265 dictionary = new Dictionary<string, BindableProperty>();
268 if (true == AddParentTypeProperty(type.BaseType, dictionary) && true == isCurDictNull)
270 bindablePropertyOfType.Add(type, dictionary);
273 baseTypePropertyHasBeenAdded.Add(type);
278 /// Gets the type declaring the BindableProperty.
280 public Type DeclaringType { get; private set; }
283 /// Gets the default BindingMode.
285 public BindingMode DefaultBindingMode { get; private set; }
288 /// Gets the default value for the BindableProperty.
290 public object DefaultValue { get; }
293 /// Gets a value indicating if the BindableProperty is created form a BindablePropertyKey.
295 public bool IsReadOnly { get; private set; }
298 /// Gets the property name.
300 public string PropertyName { get; }
303 /// Gets the type of the BindableProperty.
305 public Type ReturnType { get; }
307 internal BindablePropertyBindingChanging BindingChanging { get; private set; }
309 internal CoerceValueDelegate CoerceValue { get; private set; }
311 internal CreateDefaultValueDelegate DefaultValueCreator { get; }
313 internal BindingPropertyChangedDelegate PropertyChanged { get; private set; }
315 internal BindingPropertyChangingDelegate PropertyChanging { get; private set; }
317 internal System.Reflection.TypeInfo ReturnTypeInfo { get; }
319 internal ValidateValueDelegate ValidateValue { get; private set; }
322 /// Deprecated. Do not use.
324 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
325 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
326 /// <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</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 BindableProperty.</returns>
335 [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
336 public static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
337 ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
338 BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
339 CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
341 return Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, defaultValueCreator: defaultValueCreator);
345 /// Creates a new instance of the BindableProperty class.
347 /// <param name="propertyName">The name of the BindableProperty.</param>
348 /// <param name="returnType">The type of the property.</param>
349 /// <param name="declaringType">The type of the declaring object.</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 BindableProperty.</returns>
358 public static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue = null, BindingMode defaultBindingMode = BindingMode.OneWay,
359 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
360 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
362 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
363 defaultValueCreator: defaultValueCreator);
367 /// Deprecated. Do not use.
369 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
370 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
371 /// <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
372 /// <param name="defaultValue">The default value for the property.</param>
373 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
374 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
375 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
376 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
377 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
378 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
379 [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
380 public static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
381 BindingMode defaultBindingMode = BindingMode.OneWay, ValidateValueDelegate<TPropertyType> validateValue = null, BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null,
382 BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null, CoerceValueDelegate<TPropertyType> coerceValue = null,
383 CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
385 return CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null,
386 defaultValueCreator: defaultValueCreator);
390 /// Creates a new instance of the BindableProperty class for an attached property.
392 /// <param name="propertyName">The name of the BindableProperty.</param>
393 /// <param name="returnType">The type of the property.</param>
394 /// <param name="declaringType">The type of the declaring object.</param>
395 /// <param name="defaultValue">The default value for the property.</param>
396 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
397 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
398 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
399 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
400 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
401 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
402 /// <returns>A newly created BindableProperty.</returns>
403 public static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
404 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
405 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
407 return CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, false, defaultValueCreator);
411 /// Deprecated. Do not use.
413 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
414 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
415 /// <param name="staticgetter">An expression identifying a static method returning the value of the property using this BindableProperty as backing store.</param>
416 /// <param name="defaultValue">The default value for the property.</param>
417 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
418 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
419 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
420 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
421 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
422 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
423 /// <returns>A newly created attached read-only BindablePropertyKey.</returns>
424 [Obsolete("CreateAttachedReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
425 public static BindablePropertyKey CreateAttachedReadOnly<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue,
426 BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
427 BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
428 CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
432 new BindablePropertyKey(CreateAttached<TDeclarer, TPropertyType>(staticgetter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
433 defaultValueCreator));
437 /// Creates a new instance of the BindableProperty class for attached read-only properties.
439 /// <param name="propertyName">The name of the BindableProperty.</param>
440 /// <param name="returnType">The type of the property.</param>
441 /// <param name="declaringType">The type of the declaring object.</param>
442 /// <param name="defaultValue">The default value for the property.</param>
443 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
444 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
445 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
446 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
447 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
448 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
449 /// <returns>A newly created attached read-only BindablePropertyKey.</returns>
450 public static BindablePropertyKey CreateAttachedReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
451 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
452 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
455 new BindablePropertyKey(CreateAttached(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true,
456 defaultValueCreator));
460 /// Deprecated. Do not use.
462 /// <typeparam name="TDeclarer">The type of the declaring object.</typeparam>
463 /// <typeparam name="TPropertyType">The type of the property.</typeparam>
464 /// <param name="getter">An expression identifying the getter for the property using this BindableProperty as backing store.</param>
465 /// <param name="defaultValue">The default value for the property.</param>
466 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
467 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
468 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
469 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
470 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
471 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
472 /// <returns>A newly created BindablePropertyKey.</returns>
473 [Obsolete("CreateReadOnly<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
474 public static BindablePropertyKey CreateReadOnly<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue,
475 BindingMode defaultBindingMode = BindingMode.OneWayToSource, ValidateValueDelegate<TPropertyType> validateValue = null,
476 BindingPropertyChangedDelegate<TPropertyType> propertyChanged = null, BindingPropertyChangingDelegate<TPropertyType> propertyChanging = null,
477 CoerceValueDelegate<TPropertyType> coerceValue = null, CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
479 return new BindablePropertyKey(Create(getter, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, null, true, defaultValueCreator));
483 /// Creates a new instance of the BindablePropertyKey class.
485 /// <param name="propertyName">The name of the BindableProperty.</param>
486 /// <param name="returnType">The type of the property.</param>
487 /// <param name="declaringType">The type of the declaring object.</param>
488 /// <param name="defaultValue">The default value for the property.</param>
489 /// <param name="defaultBindingMode">The BindingMode to use on SetBinding() if no BindingMode is given. This parameter is optional. Default is BindingMode.OneWay.</param>
490 /// <param name="validateValue">A delegate to be run when a value is set. This parameter is optional. Default is null.</param>
491 /// <param name="propertyChanged">A delegate to be run when the value has changed. This parameter is optional. Default is null.</param>
492 /// <param name="propertyChanging">A delegate to be run when the value will change. This parameter is optional. Default is null.</param>
493 /// <param name="coerceValue">A delegate used to coerce the range of a value. This parameter is optional. Default is null.</param>
494 /// <param name="defaultValueCreator">A Func used to initialize default value for reference types.</param>
495 /// <returns>A newly created BindablePropertyKey.</returns>
496 public static BindablePropertyKey CreateReadOnly(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWayToSource,
497 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
498 CoerceValueDelegate coerceValue = null, CreateDefaultValueDelegate defaultValueCreator = null)
501 new BindablePropertyKey(new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue,
502 isReadOnly: true, defaultValueCreator: defaultValueCreator));
505 [Obsolete("Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
506 internal static BindableProperty Create<TDeclarer, TPropertyType>(Expression<Func<TDeclarer, TPropertyType>> getter, TPropertyType defaultValue, BindingMode defaultBindingMode,
507 ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
508 CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
509 CreateDefaultValueDelegate<TDeclarer, TPropertyType> defaultValueCreator = null) where TDeclarer : BindableObject
512 throw new ArgumentNullException(nameof(getter));
514 Expression expr = getter.Body;
516 var unary = expr as UnaryExpression;
518 expr = unary.Operand;
520 var member = expr as MemberExpression;
522 throw new ArgumentException("getter must be a MemberExpression", nameof(getter));
524 var property = (PropertyInfo)member.Member;
526 ValidateValueDelegate untypedValidateValue = null;
527 BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
528 BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
529 CoerceValueDelegate untypedCoerceValue = null;
530 CreateDefaultValueDelegate untypedDefaultValueCreator = null;
531 if (validateValue != null)
532 untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
533 if (propertyChanged != null)
534 untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
535 if (propertyChanging != null)
536 untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
537 if (coerceValue != null)
538 untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
539 if (defaultValueCreator != null)
540 untypedDefaultValueCreator = o => defaultValueCreator((TDeclarer)o);
542 return new BindableProperty(property.Name, property.PropertyType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged,
543 untypedBindingPropertyChanging, untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
546 internal static BindableProperty Create(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
547 BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
548 CreateDefaultValueDelegate defaultValueCreator = null)
550 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging,
551 defaultValueCreator: defaultValueCreator);
554 [Obsolete("CreateAttached<> (generic) is obsolete as of version 2.1.0 and is no longer supported.")]
555 internal static BindableProperty CreateAttached<TDeclarer, TPropertyType>(Expression<Func<BindableObject, TPropertyType>> staticgetter, TPropertyType defaultValue, BindingMode defaultBindingMode,
556 ValidateValueDelegate<TPropertyType> validateValue, BindingPropertyChangedDelegate<TPropertyType> propertyChanged, BindingPropertyChangingDelegate<TPropertyType> propertyChanging,
557 CoerceValueDelegate<TPropertyType> coerceValue, BindablePropertyBindingChanging bindingChanging, bool isReadOnly = false,
558 CreateDefaultValueDelegate<BindableObject, TPropertyType> defaultValueCreator = null)
560 if (staticgetter == null)
561 throw new ArgumentNullException(nameof(staticgetter));
563 Expression expr = staticgetter.Body;
565 var unary = expr as UnaryExpression;
567 expr = unary.Operand;
569 var methodcall = expr as MethodCallExpression;
570 if (methodcall == null)
571 throw new ArgumentException("staticgetter must be a MethodCallExpression", nameof(staticgetter));
573 MethodInfo method = methodcall.Method;
574 if (!method.Name.StartsWith("Get", StringComparison.Ordinal))
575 throw new ArgumentException("staticgetter name must start with Get", nameof(staticgetter));
577 string propertyname = method.Name.Substring(3);
579 ValidateValueDelegate untypedValidateValue = null;
580 BindingPropertyChangedDelegate untypedBindingPropertyChanged = null;
581 BindingPropertyChangingDelegate untypedBindingPropertyChanging = null;
582 CoerceValueDelegate untypedCoerceValue = null;
583 CreateDefaultValueDelegate untypedDefaultValueCreator = null;
584 if (validateValue != null)
585 untypedValidateValue = (bindable, value) => validateValue(bindable, (TPropertyType)value);
586 if (propertyChanged != null)
587 untypedBindingPropertyChanged = (bindable, oldValue, newValue) => propertyChanged(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
588 if (propertyChanging != null)
589 untypedBindingPropertyChanging = (bindable, oldValue, newValue) => propertyChanging(bindable, (TPropertyType)oldValue, (TPropertyType)newValue);
590 if (coerceValue != null)
591 untypedCoerceValue = (bindable, value) => coerceValue(bindable, (TPropertyType)value);
592 if (defaultValueCreator != null)
593 untypedDefaultValueCreator = o => defaultValueCreator(o);
595 return new BindableProperty(propertyname, method.ReturnType, typeof(TDeclarer), defaultValue, defaultBindingMode, untypedValidateValue, untypedBindingPropertyChanged, untypedBindingPropertyChanging,
596 untypedCoerceValue, bindingChanging, isReadOnly, untypedDefaultValueCreator);
599 internal static BindableProperty CreateAttached(string propertyName, Type returnType, Type declaringType, object defaultValue, BindingMode defaultBindingMode, ValidateValueDelegate validateValue,
600 BindingPropertyChangedDelegate propertyChanged, BindingPropertyChangingDelegate propertyChanging, CoerceValueDelegate coerceValue, BindablePropertyBindingChanging bindingChanging,
601 bool isReadOnly, CreateDefaultValueDelegate defaultValueCreator = null)
603 return new BindableProperty(propertyName, returnType, declaringType, defaultValue, defaultBindingMode, validateValue, propertyChanged, propertyChanging, coerceValue, bindingChanging, isReadOnly,
604 defaultValueCreator);
607 internal object GetDefaultValue(BindableObject bindable)
609 if (DefaultValueCreator != null)
610 return DefaultValueCreator(bindable);
615 internal bool TryConvert(ref object value)
619 return !ReturnTypeInfo.IsValueType || ReturnTypeInfo.IsGenericType && ReturnTypeInfo.GetGenericTypeDefinition() == typeof(Nullable<>);
622 Type valueType = value.GetType();
623 Type type = ReturnType;
625 // TODO This is temporary fix before deleting CreateByXaml flag in BindableProperty.
626 if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Tizen.NUI.BaseComponents.Selector<>) && valueType.GetGenericArguments()[0] == ReturnType)
631 // Dont support arbitrary IConvertible by limiting which types can use this
632 Type[] convertableTo;
633 TypeConverter typeConverterTo;
634 if (SimpleConvertTypes.TryGetValue(valueType, out convertableTo) && Array.IndexOf(convertableTo, type) != -1)
636 value = Convert.ChangeType(value, type);
638 else if (WellKnownConvertTypes.TryGetValue(type, out typeConverterTo) && typeConverterTo.CanConvertFrom(valueType))
640 value = typeConverterTo.ConvertFromInvariantString(value.ToString());
642 else if (UserCustomConvertTypes.TryGetValue(type, out typeConverterTo) && typeConverterTo.CanConvertFrom(valueType))
644 //Modification for NUI XAML : user defined converter for DynamicResource can be added
645 value = typeConverterTo.ConvertFromInvariantString(value.ToString());
647 else if (!ReturnTypeInfo.IsAssignableFrom(valueType.GetTypeInfo()))
649 var cast = type.GetImplicitConversionOperator(fromType: valueType, toType: type)
650 ?? valueType.GetImplicitConversionOperator(fromType: valueType, toType: type);
655 value = cast.Invoke(null, new[] { value });
661 internal delegate void BindablePropertyBindingChanging(BindableObject bindable, BindingBase oldValue, BindingBase newValue);