[NUI] Fix build warning CA1507
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / XamlBinding / BindableObject.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Diagnostics;
5 using System.Reflection;
6 using System.Runtime.CompilerServices;
7 using Tizen.NUI.Binding.Internals;
8
9 namespace Tizen.NUI.Binding
10 {
11     /// <summary>
12     /// Provides a mechanism by which application developers can propagate changes that are made to data in one object to another, by enabling validation, type coercion, and an event system.
13     /// </summary>
14     [EditorBrowsable(EditorBrowsableState.Never)]
15     public abstract class BindableObject : INotifyPropertyChanged, IDynamicResourceHandler
16     {
17         /// <summary>
18         /// Implements the bound property whose interface is provided by the BindingContext property.
19         /// </summary>
20         [EditorBrowsable(EditorBrowsableState.Never)]
21         public static readonly BindableProperty BindingContextProperty =
22             BindableProperty.Create(nameof(BindingContext), typeof(object), typeof(BindableObject), default(object),
23                                     BindingMode.OneWay, null, BindingContextPropertyChanged, null, null, BindingContextPropertyBindingChanging);
24
25         readonly List<BindablePropertyContext> _properties = new List<BindablePropertyContext>(4);
26
27         bool _applying;
28         object _inheritedContext;
29
30         /// <summary>
31         /// Gets or sets object that contains the properties that will be targeted by the bound properties that belong to this BindableObject.
32         /// </summary>
33         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
34         [EditorBrowsable(EditorBrowsableState.Never)]
35         public object BindingContext
36         {
37             get { return _inheritedContext ?? GetValue(BindingContextProperty); }
38             set { SetValue(BindingContextProperty, value); }
39         }
40
41         void IDynamicResourceHandler.SetDynamicResource(BindableProperty property, string key)
42         {
43             SetDynamicResource(property, key, false);
44         }
45
46         /// <summary>
47         /// Raised when a property has changed.
48         /// </summary>
49         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
50         [EditorBrowsable(EditorBrowsableState.Never)]
51         public event PropertyChangedEventHandler PropertyChanged;
52
53         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
54         [EditorBrowsable(EditorBrowsableState.Never)]
55         public virtual void CopyFrom(BindableObject that)
56         {
57             if (null != that)
58             {
59                 Dictionary<string, BindableProperty> nameToBindableProperty1;
60                 Type type1 = this.GetType();
61                 BindableProperty.GetBindablePropertysOfType(type1, out nameToBindableProperty1);
62
63                 Dictionary<string, BindableProperty> nameToBindableProperty2;
64                 Type type2 = that.GetType();
65                 BindableProperty.GetBindablePropertysOfType(type2, out nameToBindableProperty2);
66
67                 if (null != nameToBindableProperty1)
68                 {
69                     foreach (KeyValuePair<string, BindableProperty> keyValuePair in nameToBindableProperty1)
70                     {
71                         BindableProperty bindableProperty;
72                         nameToBindableProperty2.TryGetValue(keyValuePair.Key, out bindableProperty);
73
74                         if (null != bindableProperty)
75                         {
76                             object value = that.GetValue(bindableProperty);
77
78                             if (null != value)
79                             {
80                                 SetValue(keyValuePair.Value, value);
81                             }
82                         }
83                     }
84                 }
85             }
86         }
87
88         /// <summary>
89         /// Raised whenever the BindingContext property changes.
90         /// </summary>
91         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
92         [EditorBrowsable(EditorBrowsableState.Never)]
93         public event EventHandler BindingContextChanged;
94
95         internal void ClearValue(BindableProperty property, bool fromStyle)
96         {
97             ClearValue(property, fromStyle: fromStyle, checkAccess: true);
98         }
99
100         /// <summary>
101         /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue.
102         /// </summary>
103         /// <param name="property">The BindableProperty to clear</param>
104         internal void ClearValue(BindableProperty property)
105         {
106             ClearValue(property, fromStyle: false, checkAccess: true);
107         }
108
109         /// <summary>
110         /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue for the property that is identified by propertyKey.
111         /// </summary>
112         /// <param name="propertyKey">The BindablePropertyKey that identifies the BindableProperty to clear.</param>
113         internal void ClearValue(BindablePropertyKey propertyKey)
114         {
115             if (propertyKey == null)
116                 throw new ArgumentNullException(nameof(propertyKey));
117
118             ClearValue(propertyKey.BindableProperty, fromStyle:false, checkAccess: false);
119         }
120
121         /// <summary>
122         /// Return true if the target property exists and has been set.
123         /// </summary>
124         /// <param name="targetProperty">The target property</param>
125         /// <returns>return true if the target property exists and has been set</returns>
126         internal bool IsSet(BindableProperty targetProperty)
127         {
128             if (targetProperty == null)
129                 throw new ArgumentNullException(nameof(targetProperty));
130
131             var bpcontext = GetContext(targetProperty);
132             return bpcontext != null
133                 && (bpcontext.Attributes & BindableContextAttributes.IsDefaultValue) == 0;
134         }
135
136         /// <summary>
137         /// Returns the value that is contained the BindableProperty.
138         /// </summary>
139         /// <param name="property">The BindableProperty for which to get the value.</param>
140         /// <returns>The value that is contained the BindableProperty</returns>
141         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
142         [EditorBrowsable(EditorBrowsableState.Never)]
143         public object GetValue(BindableProperty property)
144         {
145             if (property == null)
146                 throw new ArgumentNullException(nameof(property));
147
148             BindablePropertyContext context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property);
149
150             if (context == null)
151                 return property.DefaultValue;
152
153             return context.Value;
154         }
155
156         /// <summary>
157         /// Raised when a property is about to change.
158         /// </summary>
159         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
160         [EditorBrowsable(EditorBrowsableState.Never)]
161         public event PropertyChangingEventHandler PropertyChanging;
162
163         /// <summary>
164         /// Removes a previously set binding.
165         /// </summary>
166         /// <param name="property">The BindableProperty from which to remove bindings.</param>
167         internal void RemoveBinding(BindableProperty property)
168         {
169             if (property == null)
170                 throw new ArgumentNullException(nameof(property));
171
172             BindablePropertyContext context = GetContext(property);
173             if (context == null || context.Binding == null)
174                 return;
175
176             RemoveBinding(property, context);
177         }
178
179         /// <summary>
180         /// Assigns a binding to a property.
181         /// </summary>
182         /// <param name="targetProperty">The BindableProperty on which to set a binding.</param>
183         /// <param name="binding">The binding to set.</param>
184         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
185         [EditorBrowsable(EditorBrowsableState.Never)]
186         public void SetBinding(BindableProperty targetProperty, BindingBase binding)
187         {
188             SetBinding(targetProperty, binding, false);
189         }
190
191         private bool isCreateByXaml = false;
192         /// Only used by the IL of xaml, will never changed to not hidden.
193         [EditorBrowsable(EditorBrowsableState.Never)]
194         public virtual bool IsCreateByXaml
195         {
196             get
197             {
198                 return isCreateByXaml;
199             }
200             set
201             {
202                 isCreateByXaml = value;
203             }
204         }
205
206         /// <summary>
207         /// Sets the value of the specified property.
208         /// </summary>
209         /// <param name="property">The BindableProperty on which to assign a value.</param>
210         /// <param name="value">The value to set.</param>
211         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
212         [EditorBrowsable(EditorBrowsableState.Never)]
213         public void SetValue(BindableProperty property, object value)
214         {
215             if (true == isCreateByXaml)
216             {
217                 SetValue(property, value, false, true);
218             }
219             else
220             {
221                 property.PropertyChanged?.Invoke(this, null, value);
222
223                 OnPropertyChanged(property.PropertyName);
224             }
225         }
226
227         internal void SetValueAndForceSendChangeSignal(BindableProperty property, object value)
228         {
229             if (property == null)
230                 throw new ArgumentNullException(nameof(property));
231
232             if (true == isCreateByXaml)
233             {
234                 if (property.IsReadOnly)
235                     throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
236
237                 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
238                     SetValuePrivateFlags.ManuallySet | SetValuePrivateFlags.CheckAccess, true);
239             }
240             else
241             {
242                 property.PropertyChanged?.Invoke(this, null, value);
243             }
244         }
245
246         /// <summary>
247         /// Sets the value of the propertyKey.
248         /// </summary>
249         /// <param name="propertyKey">The BindablePropertyKey on which to assign a value.</param>
250         /// <param name="value">The value to set.</param>
251         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
252         [EditorBrowsable(EditorBrowsableState.Never)]
253         public void SetValue(BindablePropertyKey propertyKey, object value)
254         {
255             if (propertyKey == null)
256                 throw new ArgumentNullException(nameof(propertyKey));
257
258             SetValue(propertyKey.BindableProperty, value, false, false);
259         }
260
261         /// <summary>
262         /// Set the inherited context to a neated element.
263         /// </summary>
264         /// <param name="bindable">The object on which to set the inherited binding context.</param>
265         /// <param name="value">The inherited context to set.</param>
266         [EditorBrowsable(EditorBrowsableState.Never)]
267         public static void SetInheritedBindingContext(BindableObject bindable, object value)
268         {
269             BindablePropertyContext bpContext = bindable.GetContext(BindingContextProperty);
270             if (bpContext != null && ((bpContext.Attributes & BindableContextAttributes.IsManuallySet) != 0))
271                 return;
272
273             object oldContext = bindable._inheritedContext;
274
275             if (ReferenceEquals(oldContext, value))
276                 return;
277
278             if (bpContext != null && oldContext == null)
279                 oldContext = bpContext.Value;
280
281             if (bpContext != null && bpContext.Binding != null)
282             {
283                 bpContext.Binding.Context = value;
284                 bindable._inheritedContext = null;
285             }
286             else
287             {
288                 bindable._inheritedContext = value;
289             }
290
291             bindable.ApplyBindings(skipBindingContext:false, fromBindingContextChanged:true);
292             bindable.OnBindingContextChanged();
293         }
294
295         /// <summary>
296         /// Apply the bindings to BindingContext.
297         /// </summary>
298         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
299         [EditorBrowsable(EditorBrowsableState.Never)]
300         protected void ApplyBindings()
301         {
302             ApplyBindings(skipBindingContext: false, fromBindingContextChanged: false);
303         }
304
305         /// <summary>
306         /// Override this method to execute an action when the BindingContext changes.
307         /// </summary>
308         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
309         [EditorBrowsable(EditorBrowsableState.Never)]
310         protected virtual void OnBindingContextChanged()
311         {
312             BindingContextChanged?.Invoke(this, EventArgs.Empty);
313         }
314
315         /// <summary>
316         /// Call this method from a child class to notify that a change happened on a property.
317         /// </summary>
318         /// <param name="propertyName">The name of the property that changed.</param>
319         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
320         [EditorBrowsable(EditorBrowsableState.Never)]
321         protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
322             => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
323
324         /// <summary>
325         /// Call this method from a child class to notify that a change is going to happen on a property.
326         /// </summary>
327         /// <param name="propertyName">The name of the property that is changing.</param>
328         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
329         [EditorBrowsable(EditorBrowsableState.Never)]
330         protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null)
331             => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
332
333         /// <summary>
334         /// Unapplies all previously set bindings.
335         /// </summary>
336         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
337         [EditorBrowsable(EditorBrowsableState.Never)]
338         protected void UnapplyBindings()
339         {
340             for (int i = 0, _propertiesCount = _properties.Count; i < _propertiesCount; i++) {
341                 BindablePropertyContext context = _properties [i];
342                 if (context.Binding == null)
343                     continue;
344
345                 context.Binding.Unapply();
346             }
347         }
348
349         internal bool GetIsBound(BindableProperty targetProperty)
350         {
351             if (targetProperty == null)
352                 throw new ArgumentNullException(nameof(targetProperty));
353
354             BindablePropertyContext bpcontext = GetContext(targetProperty);
355             return bpcontext != null && bpcontext.Binding != null;
356         }
357
358         /// <summary>
359         /// Returns the value that is contained the BindableProperty.
360         /// </summary>
361         /// <param name="property0">The BindableProperty instance.</param>
362         /// <param name="property1">The BindableProperty instance.</param>
363         /// <returns>The value that is contained the BindableProperty</returns>
364         internal object[] GetValues(BindableProperty property0, BindableProperty property1)
365         {
366             var values = new object[2];
367
368             for (var i = 0; i < _properties.Count; i++)
369             {
370                 BindablePropertyContext context = _properties[i];
371
372                 if (ReferenceEquals(context.Property, property0))
373                 {
374                     values[0] = context.Value;
375                     property0 = null;
376                 }
377                 else if (ReferenceEquals(context.Property, property1))
378                 {
379                     values[1] = context.Value;
380                     property1 = null;
381                 }
382
383                 if (property0 == null && property1 == null)
384                     return values;
385             }
386
387             if (!ReferenceEquals(property0, null))
388                 values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
389             if (!ReferenceEquals(property1, null))
390                 values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
391
392             return values;
393         }
394
395         /// <summary>
396         /// Returns the value that is contained the BindableProperty.
397         /// </summary>
398         /// <param name="property0">The BindableProperty instance.</param>
399         /// <param name="property1">The BindableProperty instance.</param>
400         /// <param name="property2">The BindableProperty instance.</param>
401         /// <returns>The value that is contained the BindableProperty</returns>
402         internal object[] GetValues(BindableProperty property0, BindableProperty property1, BindableProperty property2)
403         {
404             var values = new object[3];
405
406             for (var i = 0; i < _properties.Count; i++)
407             {
408                 BindablePropertyContext context = _properties[i];
409
410                 if (ReferenceEquals(context.Property, property0))
411                 {
412                     values[0] = context.Value;
413                     property0 = null;
414                 }
415                 else if (ReferenceEquals(context.Property, property1))
416                 {
417                     values[1] = context.Value;
418                     property1 = null;
419                 }
420                 else if (ReferenceEquals(context.Property, property2))
421                 {
422                     values[2] = context.Value;
423                     property2 = null;
424                 }
425
426                 if (property0 == null && property1 == null && property2 == null)
427                     return values;
428             }
429
430             if (!ReferenceEquals(property0, null))
431                 values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
432             if (!ReferenceEquals(property1, null))
433                 values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
434             if (!ReferenceEquals(property2, null))
435                 values[2] = property2.DefaultValueCreator == null ? property2.DefaultValue : CreateAndAddContext(property2).Value;
436
437             return values;
438         }
439
440         /// <summary>
441         /// Returns the value that is contained the BindableProperty.
442         /// </summary>
443         /// <param name="properties">The array of the BindableProperty instances</param>
444         /// <returns>The values that is contained the BindableProperty instances.</returns>
445         internal object[] GetValues(params BindableProperty[] properties)
446         {
447             var values = new object[properties.Length];
448             for (var i = 0; i < _properties.Count; i++) {
449                 var context = _properties[i];
450                 var index = properties.IndexOf(context.Property);
451                 if (index < 0)
452                     continue;
453                 values[index] = context.Value;
454             }
455             for (var i = 0; i < values.Length; i++) {
456                 if (!ReferenceEquals(values[i], null))
457                     continue;
458                 values[i] = properties[i].DefaultValueCreator == null ? properties[i].DefaultValue : CreateAndAddContext(properties[i]).Value;
459             }
460             return values;
461         }
462
463         internal virtual void OnRemoveDynamicResource(BindableProperty property)
464         {
465         }
466
467         internal virtual void OnSetDynamicResource(BindableProperty property, string key)
468         {
469         }
470
471         internal void RemoveDynamicResource(BindableProperty property)
472         {
473             if (property == null)
474                 throw new ArgumentNullException(nameof(property));
475
476             OnRemoveDynamicResource(property);
477             BindablePropertyContext context = GetOrCreateContext(property);
478             context.Attributes &= ~BindableContextAttributes.IsDynamicResource;
479         }
480
481         internal void SetBinding(BindableProperty targetProperty, BindingBase binding, bool fromStyle)
482         {
483             if (targetProperty == null)
484                 throw new ArgumentNullException(nameof(targetProperty));
485             if (binding == null)
486                 throw new ArgumentNullException(nameof(binding));
487
488             if (fromStyle && !CanBeSetFromStyle(targetProperty))
489                 return;
490
491             var context = GetOrCreateContext(targetProperty);
492             if (fromStyle)
493                 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
494             else
495                 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
496
497             if (context.Binding != null)
498                 context.Binding.Unapply();
499
500             BindingBase oldBinding = context.Binding;
501             context.Binding = binding;
502
503             targetProperty.BindingChanging?.Invoke(this, oldBinding, binding);
504
505             binding.Apply(BindingContext, this, targetProperty);
506         }
507
508         bool CanBeSetFromStyle(BindableProperty property)
509         {
510             var context = GetContext(property);
511             if (context == null)
512                 return true;
513             if ((context.Attributes & BindableContextAttributes.IsSetFromStyle) == BindableContextAttributes.IsSetFromStyle)
514                 return true;
515             if ((context.Attributes & BindableContextAttributes.IsDefaultValue) == BindableContextAttributes.IsDefaultValue)
516                 return true;
517             if ((context.Attributes & BindableContextAttributes.IsDefaultValueCreated) == BindableContextAttributes.IsDefaultValueCreated)
518                 return true;
519             return false;
520         }
521
522         internal void SetDynamicResource(BindableProperty property, string key)
523         {
524             SetDynamicResource(property, key, false);
525         }
526
527         internal void SetDynamicResource(BindableProperty property, string key, bool fromStyle)
528         {
529             if (property == null)
530                 throw new ArgumentNullException(nameof(property));
531             if (string.IsNullOrEmpty(key))
532                 throw new ArgumentNullException(nameof(key));
533             if (fromStyle && !CanBeSetFromStyle(property))
534                 return;
535
536             var context = GetOrCreateContext(property);
537
538             context.Attributes |= BindableContextAttributes.IsDynamicResource;
539             if (fromStyle)
540                 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
541             else
542                 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
543
544             OnSetDynamicResource(property, key);
545         }
546
547         internal void SetValue(BindableProperty property, object value, bool fromStyle)
548         {
549             SetValue(property, value, fromStyle, true);
550         }
551
552         internal void SetValueCore(BindablePropertyKey propertyKey, object value, SetValueFlags attributes = SetValueFlags.None)
553         {
554             SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None, false);
555         }
556
557         /// <summary>
558         /// For internal use.
559         /// </summary>
560         /// <param name="property">The BindableProperty on which to assign a value.</param>
561         /// <param name="value">The value to set</param>
562         /// <param name="attributes">The set value flag</param>
563         [EditorBrowsable(EditorBrowsableState.Never)]
564         internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None)
565         {
566             SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, false);
567         }
568
569         internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, bool forceSendChangeSignal)
570         {
571             bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
572             bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
573             bool silent = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
574             bool fromStyle = (privateAttributes & SetValuePrivateFlags.FromStyle) != 0;
575             bool converted = (privateAttributes & SetValuePrivateFlags.Converted) != 0;
576
577             if (property == null)
578                 throw new ArgumentNullException(nameof(property));
579             if (checkAccess && property.IsReadOnly)
580             {
581                 Debug.WriteLine("Can not set the BindableProperty \"{0}\" because it is readonly.", property.PropertyName);
582                 return;
583             }
584
585             if (!converted && !property.TryConvert(ref value))
586             {
587                 Console.WriteLine("SetValue", "Can not convert {0} to type '{1}'", value, property.ReturnType);
588                 return;
589             }
590
591             if (property.ValidateValue != null && !property.ValidateValue(this, value))
592                 throw new ArgumentException("Value was an invalid value for " + property.PropertyName, nameof(value));
593
594             if (property.CoerceValue != null)
595                 value = property.CoerceValue(this, value);
596
597             BindablePropertyContext context = GetOrCreateContext(property);
598             if (manuallySet) {
599                 context.Attributes |= BindableContextAttributes.IsManuallySet;
600                 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
601             } else
602                 context.Attributes &= ~BindableContextAttributes.IsManuallySet;
603
604             if (fromStyle)
605                 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
606             // else omitted on purpose
607
608             bool currentlyApplying = _applying;
609
610             if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
611             {
612                 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
613                 if (delayQueue == null)
614                     context.DelayedSetters = delayQueue = new Queue<SetValueArgs>();
615
616                 delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
617             }
618             else
619             {
620                 context.Attributes |= BindableContextAttributes.IsBeingSet;
621                 SetValueActual(property, context, value, currentlyApplying, forceSendChangeSignal, attributes, silent);
622
623                 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
624                 if (delayQueue != null)
625                 {
626                     while (delayQueue.Count > 0)
627                     {
628                         SetValueArgs s = delayQueue.Dequeue();
629                         SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, forceSendChangeSignal, s.Attributes);
630                     }
631
632                     context.DelayedSetters = null;
633                 }
634
635                 context.Attributes &= ~BindableContextAttributes.IsBeingSet;
636             }
637         }
638
639         internal void ApplyBindings(bool skipBindingContext, bool fromBindingContextChanged)
640         {
641             var prop = _properties.ToArray();
642             for (int i = 0, propLength = prop.Length; i < propLength; i++) {
643                 BindablePropertyContext context = prop [i];
644                 BindingBase binding = context.Binding;
645                 if (binding == null)
646                     continue;
647
648                 if (skipBindingContext && ReferenceEquals(context.Property, BindingContextProperty))
649                     continue;
650
651                 binding.Unapply(fromBindingContextChanged: fromBindingContextChanged);
652                 binding.Apply(BindingContext, this, context.Property, fromBindingContextChanged: fromBindingContextChanged);
653             }
654         }
655
656         static void BindingContextPropertyBindingChanging(BindableObject bindable, BindingBase oldBindingBase, BindingBase newBindingBase)
657         {
658             object context = bindable._inheritedContext;
659             var oldBinding = oldBindingBase as Binding;
660             var newBinding = newBindingBase as Binding;
661
662             if (context == null && oldBinding != null)
663                 context = oldBinding.Context;
664             if (context != null && newBinding != null)
665                 newBinding.Context = context;
666         }
667
668         static void BindingContextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
669         {
670             bindable._inheritedContext = null;
671             bindable.ApplyBindings(skipBindingContext: true, fromBindingContextChanged:true);
672             bindable.OnBindingContextChanged();
673         }
674
675         void ClearValue(BindableProperty property, bool fromStyle, bool checkAccess)
676         {
677             if (property == null)
678                 throw new ArgumentNullException(nameof(property));
679
680             if (checkAccess && property.IsReadOnly)
681                 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
682
683             BindablePropertyContext bpcontext = GetContext(property);
684             if (bpcontext == null)
685                 return;
686
687             if (fromStyle && !CanBeSetFromStyle(property))
688                 return;
689
690             object original = bpcontext.Value;
691
692             object newValue = property.GetDefaultValue(this);
693
694             bool same = Equals(original, newValue);
695             if (!same)
696             {
697                 property.PropertyChanging?.Invoke(this, original, newValue);
698
699                 OnPropertyChanging(property.PropertyName);
700             }
701
702             bpcontext.Attributes &= ~BindableContextAttributes.IsManuallySet;
703             bpcontext.Value = newValue;
704             if (property.DefaultValueCreator == null)
705                 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValue;
706             else
707                 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValueCreated;
708
709             if (!same)
710             {
711                 OnPropertyChanged(property.PropertyName);
712                 property.PropertyChanged?.Invoke(this, original, newValue);
713             }
714         }
715
716         [MethodImpl(MethodImplOptions.AggressiveInlining)]
717         BindablePropertyContext CreateAndAddContext(BindableProperty property)
718         {
719             var context = new BindablePropertyContext { Property = property, Value = property.DefaultValueCreator != null ? property.DefaultValueCreator(this) : property.DefaultValue };
720
721             if (property.DefaultValueCreator == null)
722                 context.Attributes = BindableContextAttributes.IsDefaultValue;
723             else
724                 context.Attributes = BindableContextAttributes.IsDefaultValueCreated;
725
726             _properties.Add(context);
727             return context;
728         }
729
730         [MethodImpl(MethodImplOptions.AggressiveInlining)]
731         BindablePropertyContext GetContext(BindableProperty property)
732         {
733             List<BindablePropertyContext> properties = _properties;
734
735             for (var i = 0; i < properties.Count; i++)
736             {
737                 BindablePropertyContext context = properties[i];
738                 if (ReferenceEquals(context.Property, property))
739                     return context;
740             }
741
742             return null;
743         }
744
745         [MethodImpl(MethodImplOptions.AggressiveInlining)]
746         BindablePropertyContext GetOrCreateContext(BindableProperty property)
747         {
748             BindablePropertyContext context = GetContext(property);
749             if (context == null)
750             {
751                 context = CreateAndAddContext(property);
752             }
753             else if (property.DefaultValueCreator != null )
754             {
755                 context.Value = property.DefaultValueCreator(this); //Update Value from dali
756             }//added by xb.teng
757
758             return context;
759         }
760
761         void RemoveBinding(BindableProperty property, BindablePropertyContext context)
762         {
763             context.Binding.Unapply();
764
765             property.BindingChanging?.Invoke(this, context.Binding, null);
766
767             context.Binding = null;
768         }
769
770         void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
771         {
772             if (property == null)
773                 throw new ArgumentNullException(nameof(property));
774
775             if (checkAccess && property.IsReadOnly)
776                 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
777
778             if (fromStyle && !CanBeSetFromStyle(property))
779                 return;
780
781             SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
782                 (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0),
783                 false);
784         }
785
786         void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, bool forceSendChangeSignal, SetValueFlags attributes, bool silent = false)
787         {
788             object original = context.Value;
789             bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0;
790             bool clearDynamicResources = (attributes & SetValueFlags.ClearDynamicResource) != 0;
791             bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0;
792             bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0;
793
794             bool same = ReferenceEquals(context.Property, BindingContextProperty) ? ReferenceEquals(value, original) : Equals(value, original);
795             if (!silent && (!same || raiseOnEqual))
796             {
797                 property.PropertyChanging?.Invoke(this, original, value);
798
799                 OnPropertyChanging(property.PropertyName);
800             }
801
802             if (!same || raiseOnEqual)
803             {
804                 context.Value = value;
805             }
806
807             context.Attributes &= ~BindableContextAttributes.IsDefaultValue;
808             context.Attributes &= ~BindableContextAttributes.IsDefaultValueCreated;
809
810             if ((context.Attributes & BindableContextAttributes.IsDynamicResource) != 0 && clearDynamicResources)
811                 RemoveDynamicResource(property);
812
813             BindingBase binding = context.Binding;
814             if (binding != null)
815             {
816                 if (clearOneWayBindings && binding.GetRealizedMode(property) == BindingMode.OneWay || clearTwoWayBindings && binding.GetRealizedMode(property) == BindingMode.TwoWay)
817                 {
818                     RemoveBinding(property, context);
819                     binding = null;
820                 }
821             }
822
823             if (!silent)
824             {
825                 if ((!same || raiseOnEqual))
826                 {
827                     property.PropertyChanged?.Invoke(this, original, value);
828
829                     if (binding != null && !currentlyApplying)
830                     {
831                         _applying = true;
832                         binding.Apply(true);
833                         _applying = false;
834                     }
835
836                     OnPropertyChanged(property.PropertyName);
837                 }
838                 else if (true == same && true == forceSendChangeSignal)
839                 {
840                     if (binding != null && !currentlyApplying)
841                     {
842                         _applying = true;
843                         binding.Apply(true);
844                         _applying = false;
845                     }
846
847                     OnPropertyChanged(property.PropertyName);
848                 }
849             }
850         }
851
852         [Flags]
853         enum BindableContextAttributes
854         {
855             IsManuallySet = 1 << 0,
856             IsBeingSet = 1 << 1,
857             IsDynamicResource = 1 << 2,
858             IsSetFromStyle = 1 << 3,
859             IsDefaultValue = 1 << 4,
860             IsDefaultValueCreated = 1 << 5,
861         }
862
863         class BindablePropertyContext
864         {
865             public BindableContextAttributes Attributes;
866             public BindingBase Binding;
867             public Queue<SetValueArgs> DelayedSetters;
868             public BindableProperty Property;
869             public object Value;
870         }
871
872         [Flags]
873         internal enum SetValuePrivateFlags
874         {
875             None = 0,
876             CheckAccess = 1 << 0,
877             Silent = 1 << 1,
878             ManuallySet = 1 << 2,
879             FromStyle = 1 << 3,
880             Converted = 1 << 4,
881             Default = CheckAccess
882         }
883
884         class SetValueArgs
885         {
886             public readonly SetValueFlags Attributes;
887             public readonly BindablePropertyContext Context;
888             public readonly bool CurrentlyApplying;
889             public readonly BindableProperty Property;
890             public readonly object Value;
891
892             public SetValueArgs(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes)
893             {
894                 Property = property;
895                 Context = context;
896                 Value = value;
897                 CurrentlyApplying = currentlyApplying;
898                 Attributes = attributes;
899             }
900         }
901     }
902 }
903
904 namespace Tizen.NUI.Binding.Internals
905 {
906     /// <summary>
907     /// SetValueFlags. For internal use.
908     /// </summary>
909     [Flags]
910     [EditorBrowsable(EditorBrowsableState.Never)]
911     public enum SetValueFlags
912     {
913         /// <summary>
914         /// None.
915         /// </summary>
916         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
917         [EditorBrowsable(EditorBrowsableState.Never)]
918         None = 0,
919
920         /// <summary>
921         /// Clear OneWay bindings.
922         /// </summary>
923         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
924         [EditorBrowsable(EditorBrowsableState.Never)]
925         ClearOneWayBindings = 1 << 0,
926
927         /// <summary>
928         /// Clear TwoWay bindings.
929         /// </summary>
930         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
931         [EditorBrowsable(EditorBrowsableState.Never)]
932         ClearTwoWayBindings = 1 << 1,
933
934         /// <summary>
935         /// Clear dynamic resource.
936         /// </summary>
937         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
938         [EditorBrowsable(EditorBrowsableState.Never)]
939         ClearDynamicResource = 1 << 2,
940
941         /// <summary>
942         /// Raise or equal.
943         /// </summary>
944         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
945         [EditorBrowsable(EditorBrowsableState.Never)]
946         RaiseOnEqual = 1 << 3
947     }
948 }