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;
9 namespace Tizen.NUI.Binding
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.
14 [EditorBrowsable(EditorBrowsableState.Never)]
15 public abstract class BindableObject : INotifyPropertyChanged, IDynamicResourceHandler
18 /// Implements the bound property whose interface is provided by the BindingContext property.
20 [EditorBrowsable(EditorBrowsableState.Never)]
21 public static readonly BindableProperty BindingContextProperty =
22 BindableProperty.Create("BindingContext", typeof(object), typeof(BindableObject), default(object),
23 BindingMode.OneWay, null, BindingContextPropertyChanged, null, null, BindingContextPropertyBindingChanging);
25 readonly List<BindablePropertyContext> _properties = new List<BindablePropertyContext>(4);
28 object _inheritedContext;
31 /// Gets or sets object that contains the properties that will be targeted by the bound properties that belong to this BindableObject.
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
37 get { return _inheritedContext ?? GetValue(BindingContextProperty); }
38 set { SetValue(BindingContextProperty, value); }
41 void IDynamicResourceHandler.SetDynamicResource(BindableProperty property, string key)
43 SetDynamicResource(property, key, false);
47 /// Raised when a property has changed.
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;
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)
59 Dictionary<string, BindableProperty> nameToBindableProperty1;
60 Type type1 = this.GetType();
61 BindableProperty.GetBindablePropertysOfType(type1, out nameToBindableProperty1);
63 Dictionary<string, BindableProperty> nameToBindableProperty2;
64 Type type2 = that.GetType();
65 BindableProperty.GetBindablePropertysOfType(type2, out nameToBindableProperty2);
67 if (null != nameToBindableProperty1)
69 foreach (KeyValuePair<string, BindableProperty> keyValuePair in nameToBindableProperty1)
71 BindableProperty bindableProperty;
72 nameToBindableProperty2.TryGetValue(keyValuePair.Key, out bindableProperty);
74 if (null != bindableProperty)
76 object value = that.GetValue(bindableProperty);
80 SetValue(keyValuePair.Value, value);
89 /// Raised whenever the BindingContext property changes.
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;
95 internal void ClearValue(BindableProperty property, bool fromStyle)
97 ClearValue(property, fromStyle: fromStyle, checkAccess: true);
101 /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue.
103 /// <param name="property">The BindableProperty to clear</param>
104 internal void ClearValue(BindableProperty property)
106 ClearValue(property, fromStyle: false, checkAccess: true);
110 /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue for the property that is identified by propertyKey.
112 /// <param name="propertyKey">The BindablePropertyKey that identifies the BindableProperty to clear.</param>
113 internal void ClearValue(BindablePropertyKey propertyKey)
115 if (propertyKey == null)
116 throw new ArgumentNullException("propertyKey");
118 ClearValue(propertyKey.BindableProperty, fromStyle:false, checkAccess: false);
122 /// Return true if the target property exists and has been set.
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)
128 if (targetProperty == null)
129 throw new ArgumentNullException(nameof(targetProperty));
131 var bpcontext = GetContext(targetProperty);
132 return bpcontext != null
133 && (bpcontext.Attributes & BindableContextAttributes.IsDefaultValue) == 0;
137 /// Returns the value that is contained the BindableProperty.
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)
145 if (property == null)
146 throw new ArgumentNullException("property");
148 BindablePropertyContext context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property);
151 return property.DefaultValue;
153 return context.Value;
157 /// Raised when a property is about to change.
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;
164 /// Removes a previously set binding.
166 /// <param name="property">The BindableProperty from which to remove bindings.</param>
167 internal void RemoveBinding(BindableProperty property)
169 if (property == null)
170 throw new ArgumentNullException("property");
172 BindablePropertyContext context = GetContext(property);
173 if (context == null || context.Binding == null)
176 RemoveBinding(property, context);
180 /// Assigns a binding to a property.
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)
188 SetBinding(targetProperty, binding, false);
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
198 return isCreateByXaml;
202 isCreateByXaml = value;
207 /// Sets the value of the specified property.
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)
215 if (true == isCreateByXaml)
217 SetValue(property, value, false, true);
221 property.PropertyChanged?.Invoke(this, null, value);
223 OnPropertyChanged(property.PropertyName);
227 internal void SetValueAndForceSendChangeSignal(BindableProperty property, object value)
229 if (property == null)
230 throw new ArgumentNullException("property");
232 if (true == isCreateByXaml)
234 if (property.IsReadOnly)
235 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
237 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
238 SetValuePrivateFlags.ManuallySet | SetValuePrivateFlags.CheckAccess, true);
242 property.PropertyChanged?.Invoke(this, null, value);
247 /// Sets the value of the propertyKey.
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)
255 if (propertyKey == null)
256 throw new ArgumentNullException("propertyKey");
258 SetValue(propertyKey.BindableProperty, value, false, false);
262 /// Set the inherited context to a neated element.
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)
269 BindablePropertyContext bpContext = bindable.GetContext(BindingContextProperty);
270 if (bpContext != null && ((bpContext.Attributes & BindableContextAttributes.IsManuallySet) != 0))
273 object oldContext = bindable._inheritedContext;
275 if (ReferenceEquals(oldContext, value))
278 if (bpContext != null && oldContext == null)
279 oldContext = bpContext.Value;
281 if (bpContext != null && bpContext.Binding != null)
283 bpContext.Binding.Context = value;
284 bindable._inheritedContext = null;
288 bindable._inheritedContext = value;
291 bindable.ApplyBindings(skipBindingContext:false, fromBindingContextChanged:true);
292 bindable.OnBindingContextChanged();
296 /// Apply the bindings to BindingContext.
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()
302 ApplyBindings(skipBindingContext: false, fromBindingContextChanged: false);
306 /// Override this method to execute an action when the BindingContext changes.
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()
312 BindingContextChanged?.Invoke(this, EventArgs.Empty);
316 /// Call this method from a child class to notify that a change happened on a property.
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));
325 /// Call this method from a child class to notify that a change is going to happen on a property.
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));
334 /// Unapplies all previously set bindings.
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()
340 for (int i = 0, _propertiesCount = _properties.Count; i < _propertiesCount; i++) {
341 BindablePropertyContext context = _properties [i];
342 if (context.Binding == null)
345 context.Binding.Unapply();
349 internal bool GetIsBound(BindableProperty targetProperty)
351 if (targetProperty == null)
352 throw new ArgumentNullException("targetProperty");
354 BindablePropertyContext bpcontext = GetContext(targetProperty);
355 return bpcontext != null && bpcontext.Binding != null;
359 /// Returns the value that is contained the BindableProperty.
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)
366 var values = new object[2];
368 for (var i = 0; i < _properties.Count; i++)
370 BindablePropertyContext context = _properties[i];
372 if (ReferenceEquals(context.Property, property0))
374 values[0] = context.Value;
377 else if (ReferenceEquals(context.Property, property1))
379 values[1] = context.Value;
383 if (property0 == null && property1 == null)
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;
396 /// Returns the value that is contained the BindableProperty.
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)
404 var values = new object[3];
406 for (var i = 0; i < _properties.Count; i++)
408 BindablePropertyContext context = _properties[i];
410 if (ReferenceEquals(context.Property, property0))
412 values[0] = context.Value;
415 else if (ReferenceEquals(context.Property, property1))
417 values[1] = context.Value;
420 else if (ReferenceEquals(context.Property, property2))
422 values[2] = context.Value;
426 if (property0 == null && property1 == null && property2 == null)
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;
441 /// Returns the value that is contained the BindableProperty.
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)
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);
453 values[index] = context.Value;
455 for (var i = 0; i < values.Length; i++) {
456 if (!ReferenceEquals(values[i], null))
458 values[i] = properties[i].DefaultValueCreator == null ? properties[i].DefaultValue : CreateAndAddContext(properties[i]).Value;
463 internal virtual void OnRemoveDynamicResource(BindableProperty property)
467 internal virtual void OnSetDynamicResource(BindableProperty property, string key)
471 internal void RemoveDynamicResource(BindableProperty property)
473 if (property == null)
474 throw new ArgumentNullException("property");
476 OnRemoveDynamicResource(property);
477 BindablePropertyContext context = GetOrCreateContext(property);
478 context.Attributes &= ~BindableContextAttributes.IsDynamicResource;
481 internal void SetBinding(BindableProperty targetProperty, BindingBase binding, bool fromStyle)
483 if (targetProperty == null)
484 throw new ArgumentNullException("targetProperty");
486 throw new ArgumentNullException("binding");
488 if (fromStyle && !CanBeSetFromStyle(targetProperty))
491 var context = GetOrCreateContext(targetProperty);
493 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
495 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
497 if (context.Binding != null)
498 context.Binding.Unapply();
500 BindingBase oldBinding = context.Binding;
501 context.Binding = binding;
503 targetProperty.BindingChanging?.Invoke(this, oldBinding, binding);
505 binding.Apply(BindingContext, this, targetProperty);
508 bool CanBeSetFromStyle(BindableProperty property)
510 var context = GetContext(property);
513 if ((context.Attributes & BindableContextAttributes.IsSetFromStyle) == BindableContextAttributes.IsSetFromStyle)
515 if ((context.Attributes & BindableContextAttributes.IsDefaultValue) == BindableContextAttributes.IsDefaultValue)
517 if ((context.Attributes & BindableContextAttributes.IsDefaultValueCreated) == BindableContextAttributes.IsDefaultValueCreated)
522 internal void SetDynamicResource(BindableProperty property, string key)
524 SetDynamicResource(property, key, false);
527 internal void SetDynamicResource(BindableProperty property, string key, bool fromStyle)
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))
536 var context = GetOrCreateContext(property);
538 context.Attributes |= BindableContextAttributes.IsDynamicResource;
540 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
542 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
544 OnSetDynamicResource(property, key);
547 internal void SetValue(BindableProperty property, object value, bool fromStyle)
549 SetValue(property, value, fromStyle, true);
552 internal void SetValueCore(BindablePropertyKey propertyKey, object value, SetValueFlags attributes = SetValueFlags.None)
554 SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None, false);
558 /// For internal use.
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)
566 SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, false);
569 internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, bool forceSendChangeSignal)
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;
577 if (property == null)
578 throw new ArgumentNullException("property");
579 if (checkAccess && property.IsReadOnly)
581 Debug.WriteLine("Can not set the BindableProperty \"{0}\" because it is readonly.", property.PropertyName);
585 if (!converted && !property.TryConvert(ref value))
587 Console.WriteLine("SetValue", "Can not convert {0} to type '{1}'", value, property.ReturnType);
591 if (property.ValidateValue != null && !property.ValidateValue(this, value))
592 throw new ArgumentException("Value was an invalid value for " + property.PropertyName, "value");
594 if (property.CoerceValue != null)
595 value = property.CoerceValue(this, value);
597 BindablePropertyContext context = GetOrCreateContext(property);
599 context.Attributes |= BindableContextAttributes.IsManuallySet;
600 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
602 context.Attributes &= ~BindableContextAttributes.IsManuallySet;
605 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
606 // else omitted on purpose
608 bool currentlyApplying = _applying;
610 if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
612 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
613 if (delayQueue == null)
614 context.DelayedSetters = delayQueue = new Queue<SetValueArgs>();
616 delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
620 context.Attributes |= BindableContextAttributes.IsBeingSet;
621 SetValueActual(property, context, value, currentlyApplying, forceSendChangeSignal, attributes, silent);
623 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
624 if (delayQueue != null)
626 while (delayQueue.Count > 0)
628 SetValueArgs s = delayQueue.Dequeue();
629 SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, forceSendChangeSignal, s.Attributes);
632 context.DelayedSetters = null;
635 context.Attributes &= ~BindableContextAttributes.IsBeingSet;
639 internal void ApplyBindings(bool skipBindingContext, bool fromBindingContextChanged)
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;
648 if (skipBindingContext && ReferenceEquals(context.Property, BindingContextProperty))
651 binding.Unapply(fromBindingContextChanged: fromBindingContextChanged);
652 binding.Apply(BindingContext, this, context.Property, fromBindingContextChanged: fromBindingContextChanged);
656 static void BindingContextPropertyBindingChanging(BindableObject bindable, BindingBase oldBindingBase, BindingBase newBindingBase)
658 object context = bindable._inheritedContext;
659 var oldBinding = oldBindingBase as Binding;
660 var newBinding = newBindingBase as Binding;
662 if (context == null && oldBinding != null)
663 context = oldBinding.Context;
664 if (context != null && newBinding != null)
665 newBinding.Context = context;
668 static void BindingContextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
670 bindable._inheritedContext = null;
671 bindable.ApplyBindings(skipBindingContext: true, fromBindingContextChanged:true);
672 bindable.OnBindingContextChanged();
675 void ClearValue(BindableProperty property, bool fromStyle, bool checkAccess)
677 if (property == null)
678 throw new ArgumentNullException(nameof(property));
680 if (checkAccess && property.IsReadOnly)
681 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
683 BindablePropertyContext bpcontext = GetContext(property);
684 if (bpcontext == null)
687 if (fromStyle && !CanBeSetFromStyle(property))
690 object original = bpcontext.Value;
692 object newValue = property.GetDefaultValue(this);
694 bool same = Equals(original, newValue);
697 property.PropertyChanging?.Invoke(this, original, newValue);
699 OnPropertyChanging(property.PropertyName);
702 bpcontext.Attributes &= ~BindableContextAttributes.IsManuallySet;
703 bpcontext.Value = newValue;
704 if (property.DefaultValueCreator == null)
705 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValue;
707 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValueCreated;
711 OnPropertyChanged(property.PropertyName);
712 property.PropertyChanged?.Invoke(this, original, newValue);
716 [MethodImpl(MethodImplOptions.AggressiveInlining)]
717 BindablePropertyContext CreateAndAddContext(BindableProperty property)
719 var context = new BindablePropertyContext { Property = property, Value = property.DefaultValueCreator != null ? property.DefaultValueCreator(this) : property.DefaultValue };
721 if (property.DefaultValueCreator == null)
722 context.Attributes = BindableContextAttributes.IsDefaultValue;
724 context.Attributes = BindableContextAttributes.IsDefaultValueCreated;
726 _properties.Add(context);
730 [MethodImpl(MethodImplOptions.AggressiveInlining)]
731 BindablePropertyContext GetContext(BindableProperty property)
733 List<BindablePropertyContext> properties = _properties;
735 for (var i = 0; i < properties.Count; i++)
737 BindablePropertyContext context = properties[i];
738 if (ReferenceEquals(context.Property, property))
745 [MethodImpl(MethodImplOptions.AggressiveInlining)]
746 BindablePropertyContext GetOrCreateContext(BindableProperty property)
748 BindablePropertyContext context = GetContext(property);
751 context = CreateAndAddContext(property);
753 else if (property.DefaultValueCreator != null )
755 context.Value = property.DefaultValueCreator(this); //Update Value from dali
761 void RemoveBinding(BindableProperty property, BindablePropertyContext context)
763 context.Binding.Unapply();
765 property.BindingChanging?.Invoke(this, context.Binding, null);
767 context.Binding = null;
770 void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
772 if (property == null)
773 throw new ArgumentNullException("property");
775 if (checkAccess && property.IsReadOnly)
776 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
778 if (fromStyle && !CanBeSetFromStyle(property))
781 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
782 (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0),
786 void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, bool forceSendChangeSignal, SetValueFlags attributes, bool silent = false)
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;
794 bool same = ReferenceEquals(context.Property, BindingContextProperty) ? ReferenceEquals(value, original) : Equals(value, original);
795 if (!silent && (!same || raiseOnEqual))
797 property.PropertyChanging?.Invoke(this, original, value);
799 OnPropertyChanging(property.PropertyName);
802 if (!same || raiseOnEqual)
804 context.Value = value;
807 context.Attributes &= ~BindableContextAttributes.IsDefaultValue;
808 context.Attributes &= ~BindableContextAttributes.IsDefaultValueCreated;
810 if ((context.Attributes & BindableContextAttributes.IsDynamicResource) != 0 && clearDynamicResources)
811 RemoveDynamicResource(property);
813 BindingBase binding = context.Binding;
816 if (clearOneWayBindings && binding.GetRealizedMode(property) == BindingMode.OneWay || clearTwoWayBindings && binding.GetRealizedMode(property) == BindingMode.TwoWay)
818 RemoveBinding(property, context);
825 if ((!same || raiseOnEqual))
827 property.PropertyChanged?.Invoke(this, original, value);
829 if (binding != null && !currentlyApplying)
836 OnPropertyChanged(property.PropertyName);
838 else if (true == same && true == forceSendChangeSignal)
840 if (binding != null && !currentlyApplying)
847 OnPropertyChanged(property.PropertyName);
853 enum BindableContextAttributes
855 IsManuallySet = 1 << 0,
857 IsDynamicResource = 1 << 2,
858 IsSetFromStyle = 1 << 3,
859 IsDefaultValue = 1 << 4,
860 IsDefaultValueCreated = 1 << 5,
863 class BindablePropertyContext
865 public BindableContextAttributes Attributes;
866 public BindingBase Binding;
867 public Queue<SetValueArgs> DelayedSetters;
868 public BindableProperty Property;
873 internal enum SetValuePrivateFlags
876 CheckAccess = 1 << 0,
878 ManuallySet = 1 << 2,
881 Default = CheckAccess
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;
892 public SetValueArgs(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes)
897 CurrentlyApplying = currentlyApplying;
898 Attributes = attributes;
904 namespace Tizen.NUI.Binding.Internals
907 /// SetValueFlags. For internal use.
910 [EditorBrowsable(EditorBrowsableState.Never)]
911 public enum SetValueFlags
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)]
921 /// Clear OneWay bindings.
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,
928 /// Clear TwoWay bindings.
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,
935 /// Clear dynamic resource.
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,
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