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