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(nameof(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 /// <summary>Whether to allow null value when <seealso cref="CopyFrom"/>.</summary>
54 [EditorBrowsable(EditorBrowsableState.Never)]
55 protected static bool AllowNullCopy { get; set; } = false;
57 /// <summary>Copy properties of other ViewStyle to this.</summary>
58 /// <param name="other">The other BindableProperty merge to this.</param>
59 [EditorBrowsable(EditorBrowsableState.Never)]
60 public virtual void CopyFrom(BindableObject other)
62 if (null == other) return;
64 Type type1 = this.GetType();
65 BindableProperty.GetBindablePropertysOfType(type1, out var nameToBindableProperty1);
67 Type type2 = other.GetType();
68 BindableProperty.GetBindablePropertysOfType(type2, out var nameToBindableProperty2);
70 if (null != nameToBindableProperty1)
72 foreach (KeyValuePair<string, BindableProperty> keyValuePair in nameToBindableProperty1)
74 nameToBindableProperty2.TryGetValue(keyValuePair.Key, out var bindableProperty);
76 if (null != bindableProperty)
78 object value = other.GetValue(bindableProperty);
80 if (AllowNullCopy || null != value)
82 SetValue(keyValuePair.Value, value);
90 /// Raised whenever the BindingContext property changes.
92 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
93 [EditorBrowsable(EditorBrowsableState.Never)]
94 public event EventHandler BindingContextChanged;
96 internal void ClearValue(BindableProperty property, bool fromStyle)
98 ClearValue(property, fromStyle: fromStyle, checkAccess: true);
102 /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue.
104 /// <param name="property">The BindableProperty to clear</param>
105 internal void ClearValue(BindableProperty property)
107 ClearValue(property, fromStyle: false, checkAccess: true);
111 /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue for the property that is identified by propertyKey.
113 /// <param name="propertyKey">The BindablePropertyKey that identifies the BindableProperty to clear.</param>
114 internal void ClearValue(BindablePropertyKey propertyKey)
116 if (propertyKey == null)
117 throw new ArgumentNullException(nameof(propertyKey));
119 ClearValue(propertyKey.BindableProperty, fromStyle: false, checkAccess: false);
123 /// Return true if the target property exists and has been set.
125 /// <param name="targetProperty">The target property</param>
126 /// <returns>return true if the target property exists and has been set</returns>
127 internal bool IsSet(BindableProperty targetProperty)
129 if (targetProperty == null)
130 throw new ArgumentNullException(nameof(targetProperty));
132 var bpcontext = GetContext(targetProperty);
133 return bpcontext != null
134 && (bpcontext.Attributes & BindableContextAttributes.IsDefaultValue) == 0;
138 /// Returns the value that is contained the BindableProperty.
140 /// <param name="property">The BindableProperty for which to get the value.</param>
141 /// <returns>The value that is contained the BindableProperty</returns>
142 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
143 [EditorBrowsable(EditorBrowsableState.Never)]
144 public object GetValue(BindableProperty property)
146 if (property == null)
147 throw new ArgumentNullException(nameof(property));
149 BindablePropertyContext context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property);
152 return property.DefaultValue;
154 return context.Value;
158 /// Raised when a property is about to change.
160 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
161 [EditorBrowsable(EditorBrowsableState.Never)]
162 public event PropertyChangingEventHandler PropertyChanging;
165 /// Removes a previously set binding.
167 /// <param name="property">The BindableProperty from which to remove bindings.</param>
168 internal void RemoveBinding(BindableProperty property)
170 if (property == null)
171 throw new ArgumentNullException(nameof(property));
173 BindablePropertyContext context = GetContext(property);
174 if (context == null || context.Binding == null)
177 RemoveBinding(property, context);
181 /// Assigns a binding to a property.
183 /// <param name="targetProperty">The BindableProperty on which to set a binding.</param>
184 /// <param name="binding">The binding to set.</param>
185 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
186 [EditorBrowsable(EditorBrowsableState.Never)]
187 public void SetBinding(BindableProperty targetProperty, BindingBase binding)
189 SetBinding(targetProperty, binding, false);
192 private bool isCreateByXaml = false;
193 /// Only used by the IL of xaml, will never changed to not hidden.
194 [EditorBrowsable(EditorBrowsableState.Never)]
195 public virtual bool IsCreateByXaml
199 return isCreateByXaml;
203 isCreateByXaml = value;
208 /// Sets the value of the specified property.
210 /// <param name="property">The BindableProperty on which to assign a value.</param>
211 /// <param name="value">The value to set.</param>
212 /// <exception cref="ArgumentNullException"> Thrown when property is null. </exception>
213 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
214 [EditorBrowsable(EditorBrowsableState.Never)]
215 public void SetValue(BindableProperty property, object value)
217 if (true == isCreateByXaml)
219 SetValue(property, value, false, true);
223 if (null == property)
225 throw new ArgumentNullException(nameof(property));
227 property.PropertyChanged?.Invoke(this, null, value);
229 OnPropertyChanged(property.PropertyName);
233 internal void SetValueAndForceSendChangeSignal(BindableProperty property, object value)
235 if (property == null)
236 throw new ArgumentNullException(nameof(property));
238 if (true == isCreateByXaml)
240 if (property.IsReadOnly)
241 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
243 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
244 SetValuePrivateFlags.ManuallySet | SetValuePrivateFlags.CheckAccess, true);
248 property.PropertyChanged?.Invoke(this, null, value);
253 /// Sets the value of the propertyKey.
255 /// <param name="propertyKey">The BindablePropertyKey on which to assign a value.</param>
256 /// <param name="value">The value to set.</param>
257 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
258 [EditorBrowsable(EditorBrowsableState.Never)]
259 public void SetValue(BindablePropertyKey propertyKey, object value)
261 if (propertyKey == null)
262 throw new ArgumentNullException(nameof(propertyKey));
264 SetValue(propertyKey.BindableProperty, value, false, false);
268 /// Set the inherited context to a neated element.
270 /// <param name="bindable">The object on which to set the inherited binding context.</param>
271 /// <param name="value">The inherited context to set.</param>
272 /// <exception cref="ArgumentNullException"> Thrown when bindable is null. </exception>
273 [EditorBrowsable(EditorBrowsableState.Never)]
274 public static void SetInheritedBindingContext(BindableObject bindable, object value)
276 if (null == bindable)
278 throw new ArgumentNullException(nameof(bindable));
281 BindablePropertyContext bpContext = bindable.GetContext(BindingContextProperty);
282 if (bpContext != null && ((bpContext.Attributes & BindableContextAttributes.IsManuallySet) != 0))
285 object oldContext = bindable._inheritedContext;
287 if (ReferenceEquals(oldContext, value))
290 if (bpContext != null && oldContext == null)
291 oldContext = bpContext.Value;
293 if (bpContext != null && bpContext.Binding != null)
295 bpContext.Binding.Context = value;
296 bindable._inheritedContext = null;
300 bindable._inheritedContext = value;
303 bindable.ApplyBindings(skipBindingContext: false, fromBindingContextChanged: true);
304 bindable.OnBindingContextChanged();
308 /// Apply the bindings to BindingContext.
310 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
311 [EditorBrowsable(EditorBrowsableState.Never)]
312 protected void ApplyBindings()
314 ApplyBindings(skipBindingContext: false, fromBindingContextChanged: false);
318 /// Override this method to execute an action when the BindingContext changes.
320 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
321 [EditorBrowsable(EditorBrowsableState.Never)]
322 protected virtual void OnBindingContextChanged()
324 BindingContextChanged?.Invoke(this, EventArgs.Empty);
328 /// Call this method from a child class to notify that a change happened on a property.
330 /// <param name="propertyName">The name of the property that changed.</param>
331 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
332 [EditorBrowsable(EditorBrowsableState.Never)]
333 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
334 => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
337 /// Call this method from a child class to notify that a change is going to happen on a property.
339 /// <param name="propertyName">The name of the property that is changing.</param>
340 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
341 [EditorBrowsable(EditorBrowsableState.Never)]
342 protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null)
343 => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
346 /// Unapplies all previously set bindings.
348 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
349 [EditorBrowsable(EditorBrowsableState.Never)]
350 protected void UnapplyBindings()
352 for (int i = 0, _propertiesCount = _properties.Count; i < _propertiesCount; i++)
354 BindablePropertyContext context = _properties[i];
355 if (context.Binding == null)
358 context.Binding.Unapply();
362 internal bool GetIsBound(BindableProperty targetProperty)
364 if (targetProperty == null)
365 throw new ArgumentNullException(nameof(targetProperty));
367 BindablePropertyContext bpcontext = GetContext(targetProperty);
368 return bpcontext != null && bpcontext.Binding != null;
372 /// Returns the value that is contained the BindableProperty.
374 /// <param name="property0">The BindableProperty instance.</param>
375 /// <param name="property1">The BindableProperty instance.</param>
376 /// <returns>The value that is contained the BindableProperty</returns>
377 internal object[] GetValues(BindableProperty property0, BindableProperty property1)
379 var values = new object[2];
381 for (var i = 0; i < _properties.Count; i++)
383 BindablePropertyContext context = _properties[i];
385 if (ReferenceEquals(context.Property, property0))
387 values[0] = context.Value;
390 else if (ReferenceEquals(context.Property, property1))
392 values[1] = context.Value;
396 if (property0 == null && property1 == null)
400 if (!ReferenceEquals(property0, null))
401 values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
402 if (!ReferenceEquals(property1, null))
403 values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
409 /// Returns the value that is contained the BindableProperty.
411 /// <param name="property0">The BindableProperty instance.</param>
412 /// <param name="property1">The BindableProperty instance.</param>
413 /// <param name="property2">The BindableProperty instance.</param>
414 /// <returns>The value that is contained the BindableProperty</returns>
415 internal object[] GetValues(BindableProperty property0, BindableProperty property1, BindableProperty property2)
417 var values = new object[3];
419 for (var i = 0; i < _properties.Count; i++)
421 BindablePropertyContext context = _properties[i];
423 if (ReferenceEquals(context.Property, property0))
425 values[0] = context.Value;
428 else if (ReferenceEquals(context.Property, property1))
430 values[1] = context.Value;
433 else if (ReferenceEquals(context.Property, property2))
435 values[2] = context.Value;
439 if (property0 == null && property1 == null && property2 == null)
443 if (!ReferenceEquals(property0, null))
444 values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
445 if (!ReferenceEquals(property1, null))
446 values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
447 if (!ReferenceEquals(property2, null))
448 values[2] = property2.DefaultValueCreator == null ? property2.DefaultValue : CreateAndAddContext(property2).Value;
454 /// Returns the value that is contained the BindableProperty.
456 /// <param name="properties">The array of the BindableProperty instances</param>
457 /// <returns>The values that is contained the BindableProperty instances.</returns>
458 internal object[] GetValues(params BindableProperty[] properties)
460 var values = new object[properties.Length];
461 for (var i = 0; i < _properties.Count; i++)
463 var context = _properties[i];
464 var index = properties.IndexOf(context.Property);
467 values[index] = context.Value;
469 for (var i = 0; i < values.Length; i++)
471 if (!ReferenceEquals(values[i], null))
473 values[i] = properties[i].DefaultValueCreator == null ? properties[i].DefaultValue : CreateAndAddContext(properties[i]).Value;
478 internal virtual void OnRemoveDynamicResource(BindableProperty property)
482 internal virtual void OnSetDynamicResource(BindableProperty property, string key)
486 internal void RemoveDynamicResource(BindableProperty property)
488 if (property == null)
489 throw new ArgumentNullException(nameof(property));
491 OnRemoveDynamicResource(property);
492 BindablePropertyContext context = GetOrCreateContext(property);
493 context.Attributes &= ~BindableContextAttributes.IsDynamicResource;
496 internal void SetBinding(BindableProperty targetProperty, BindingBase binding, bool fromStyle)
498 if (targetProperty == null)
499 throw new ArgumentNullException(nameof(targetProperty));
501 throw new ArgumentNullException(nameof(binding));
503 if (fromStyle && !CanBeSetFromStyle(targetProperty))
506 var context = GetOrCreateContext(targetProperty);
508 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
510 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
512 if (context.Binding != null)
513 context.Binding.Unapply();
515 BindingBase oldBinding = context.Binding;
516 context.Binding = binding;
518 targetProperty.BindingChanging?.Invoke(this, oldBinding, binding);
520 binding.Apply(BindingContext, this, targetProperty);
523 bool CanBeSetFromStyle(BindableProperty property)
525 var context = GetContext(property);
528 if ((context.Attributes & BindableContextAttributes.IsSetFromStyle) == BindableContextAttributes.IsSetFromStyle)
530 if ((context.Attributes & BindableContextAttributes.IsDefaultValue) == BindableContextAttributes.IsDefaultValue)
532 if ((context.Attributes & BindableContextAttributes.IsDefaultValueCreated) == BindableContextAttributes.IsDefaultValueCreated)
537 internal void SetDynamicResource(BindableProperty property, string key)
539 SetDynamicResource(property, key, false);
542 internal void SetDynamicResource(BindableProperty property, string key, bool fromStyle)
544 if (property == null)
545 throw new ArgumentNullException(nameof(property));
546 if (string.IsNullOrEmpty(key))
547 throw new ArgumentNullException(nameof(key));
548 if (fromStyle && !CanBeSetFromStyle(property))
551 var context = GetOrCreateContext(property);
553 context.Attributes |= BindableContextAttributes.IsDynamicResource;
555 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
557 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
559 OnSetDynamicResource(property, key);
562 internal void SetValue(BindableProperty property, object value, bool fromStyle)
564 SetValue(property, value, fromStyle, true);
567 internal void SetValueCore(BindablePropertyKey propertyKey, object value, SetValueFlags attributes = SetValueFlags.None)
569 SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None, false);
573 /// For internal use.
575 /// <param name="property">The BindableProperty on which to assign a value.</param>
576 /// <param name="value">The value to set</param>
577 /// <param name="attributes">The set value flag</param>
578 [EditorBrowsable(EditorBrowsableState.Never)]
579 internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None)
581 SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, false);
584 internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, bool forceSendChangeSignal)
586 bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
587 bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
588 bool silent = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
589 bool fromStyle = (privateAttributes & SetValuePrivateFlags.FromStyle) != 0;
590 bool converted = (privateAttributes & SetValuePrivateFlags.Converted) != 0;
592 if (property == null)
593 throw new ArgumentNullException(nameof(property));
594 if (checkAccess && property.IsReadOnly)
596 Debug.WriteLine("Can not set the BindableProperty \"{0}\" because it is readonly.", property.PropertyName);
600 if (!converted && !property.TryConvert(ref value))
602 Console.WriteLine($"SetValue : Can not convert {value} to type {property.ReturnType}");
606 if (property.ValidateValue != null && !property.ValidateValue(this, value))
607 throw new ArgumentException("Value was an invalid value for " + property.PropertyName, nameof(value));
609 if (property.CoerceValue != null)
610 value = property.CoerceValue(this, value);
612 BindablePropertyContext context = GetOrCreateContext(property);
615 context.Attributes |= BindableContextAttributes.IsManuallySet;
616 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
619 context.Attributes &= ~BindableContextAttributes.IsManuallySet;
622 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
623 // else omitted on purpose
625 bool currentlyApplying = _applying;
627 if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
629 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
630 if (delayQueue == null)
631 context.DelayedSetters = delayQueue = new Queue<SetValueArgs>();
633 delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
637 context.Attributes |= BindableContextAttributes.IsBeingSet;
638 SetValueActual(property, context, value, currentlyApplying, forceSendChangeSignal, attributes, silent);
640 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
641 if (delayQueue != null)
643 while (delayQueue.Count > 0)
645 SetValueArgs s = delayQueue.Dequeue();
646 SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, forceSendChangeSignal, s.Attributes);
649 context.DelayedSetters = null;
652 context.Attributes &= ~BindableContextAttributes.IsBeingSet;
656 internal void ApplyBindings(bool skipBindingContext, bool fromBindingContextChanged)
658 var prop = _properties.ToArray();
659 for (int i = 0, propLength = prop.Length; i < propLength; i++)
661 BindablePropertyContext context = prop[i];
662 BindingBase binding = context.Binding;
666 if (skipBindingContext && ReferenceEquals(context.Property, BindingContextProperty))
669 binding.Unapply(fromBindingContextChanged: fromBindingContextChanged);
670 binding.Apply(BindingContext, this, context.Property, fromBindingContextChanged: fromBindingContextChanged);
674 static void BindingContextPropertyBindingChanging(BindableObject bindable, BindingBase oldBindingBase, BindingBase newBindingBase)
676 object context = bindable._inheritedContext;
677 var oldBinding = oldBindingBase as Binding;
678 var newBinding = newBindingBase as Binding;
680 if (context == null && oldBinding != null)
681 context = oldBinding.Context;
682 if (context != null && newBinding != null)
683 newBinding.Context = context;
686 static void BindingContextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
688 bindable._inheritedContext = null;
689 bindable.ApplyBindings(skipBindingContext: true, fromBindingContextChanged: true);
690 bindable.OnBindingContextChanged();
693 void ClearValue(BindableProperty property, bool fromStyle, bool checkAccess)
695 if (property == null)
696 throw new ArgumentNullException(nameof(property));
698 if (checkAccess && property.IsReadOnly)
699 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
701 BindablePropertyContext bpcontext = GetContext(property);
702 if (bpcontext == null)
705 if (fromStyle && !CanBeSetFromStyle(property))
708 object original = bpcontext.Value;
710 object newValue = property.GetDefaultValue(this);
712 bool same = Equals(original, newValue);
715 property.PropertyChanging?.Invoke(this, original, newValue);
717 OnPropertyChanging(property.PropertyName);
720 bpcontext.Attributes &= ~BindableContextAttributes.IsManuallySet;
721 bpcontext.Value = newValue;
722 if (property.DefaultValueCreator == null)
723 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValue;
725 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValueCreated;
729 OnPropertyChanged(property.PropertyName);
730 property.PropertyChanged?.Invoke(this, original, newValue);
734 [MethodImpl(MethodImplOptions.AggressiveInlining)]
735 BindablePropertyContext CreateAndAddContext(BindableProperty property)
737 var context = new BindablePropertyContext { Property = property, Value = property.DefaultValueCreator != null ? property.DefaultValueCreator(this) : property.DefaultValue };
739 if (property.DefaultValueCreator == null)
740 context.Attributes = BindableContextAttributes.IsDefaultValue;
742 context.Attributes = BindableContextAttributes.IsDefaultValueCreated;
744 _properties.Add(context);
748 [MethodImpl(MethodImplOptions.AggressiveInlining)]
749 BindablePropertyContext GetContext(BindableProperty property)
751 List<BindablePropertyContext> properties = _properties;
753 for (var i = 0; i < properties.Count; i++)
755 BindablePropertyContext context = properties[i];
756 if (ReferenceEquals(context.Property, property))
763 [MethodImpl(MethodImplOptions.AggressiveInlining)]
764 BindablePropertyContext GetOrCreateContext(BindableProperty property)
766 BindablePropertyContext context = GetContext(property);
769 context = CreateAndAddContext(property);
771 else if (property.DefaultValueCreator != null)
773 context.Value = property.DefaultValueCreator(this); //Update Value from dali
779 void RemoveBinding(BindableProperty property, BindablePropertyContext context)
781 context.Binding.Unapply();
783 property.BindingChanging?.Invoke(this, context.Binding, null);
785 context.Binding = null;
788 void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
790 if (property == null)
791 throw new ArgumentNullException(nameof(property));
793 if (checkAccess && property.IsReadOnly)
794 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
796 if (fromStyle && !CanBeSetFromStyle(property))
799 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
800 (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0),
804 void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, bool forceSendChangeSignal, SetValueFlags attributes, bool silent = false)
806 object original = context.Value;
807 bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0;
808 bool clearDynamicResources = (attributes & SetValueFlags.ClearDynamicResource) != 0;
809 bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0;
810 bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0;
812 bool same = ReferenceEquals(context.Property, BindingContextProperty) ? ReferenceEquals(value, original) : Equals(value, original);
813 if (!silent && (!same || raiseOnEqual))
815 property.PropertyChanging?.Invoke(this, original, value);
817 OnPropertyChanging(property.PropertyName);
820 if (!same || raiseOnEqual)
822 context.Value = value;
825 context.Attributes &= ~BindableContextAttributes.IsDefaultValue;
826 context.Attributes &= ~BindableContextAttributes.IsDefaultValueCreated;
828 if ((context.Attributes & BindableContextAttributes.IsDynamicResource) != 0 && clearDynamicResources)
829 RemoveDynamicResource(property);
831 BindingBase binding = context.Binding;
834 if (clearOneWayBindings && binding.GetRealizedMode(property) == BindingMode.OneWay || clearTwoWayBindings && binding.GetRealizedMode(property) == BindingMode.TwoWay)
836 RemoveBinding(property, context);
843 if ((!same || raiseOnEqual))
845 property.PropertyChanged?.Invoke(this, original, value);
847 if (binding != null && !currentlyApplying)
854 OnPropertyChanged(property.PropertyName);
856 else if (true == same && true == forceSendChangeSignal)
858 if (binding != null && !currentlyApplying)
865 OnPropertyChanged(property.PropertyName);
871 enum BindableContextAttributes
873 IsManuallySet = 1 << 0,
875 IsDynamicResource = 1 << 2,
876 IsSetFromStyle = 1 << 3,
877 IsDefaultValue = 1 << 4,
878 IsDefaultValueCreated = 1 << 5,
881 class BindablePropertyContext
883 public BindableContextAttributes Attributes;
884 public BindingBase Binding;
885 public Queue<SetValueArgs> DelayedSetters;
886 public BindableProperty Property;
891 internal enum SetValuePrivateFlags
894 CheckAccess = 1 << 0,
896 ManuallySet = 1 << 2,
899 Default = CheckAccess
904 public readonly SetValueFlags Attributes;
905 public readonly BindablePropertyContext Context;
906 public readonly bool CurrentlyApplying;
907 public readonly BindableProperty Property;
908 public readonly object Value;
910 public SetValueArgs(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes)
915 CurrentlyApplying = currentlyApplying;
916 Attributes = attributes;
922 namespace Tizen.NUI.Binding.Internals
925 /// SetValueFlags. For internal use.
928 [EditorBrowsable(EditorBrowsableState.Never)]
929 public enum SetValueFlags
934 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
935 [EditorBrowsable(EditorBrowsableState.Never)]
939 /// Clear OneWay bindings.
941 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
942 [EditorBrowsable(EditorBrowsableState.Never)]
943 ClearOneWayBindings = 1 << 0,
946 /// Clear TwoWay bindings.
948 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
949 [EditorBrowsable(EditorBrowsableState.Never)]
950 ClearTwoWayBindings = 1 << 1,
953 /// Clear dynamic resource.
955 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
956 [EditorBrowsable(EditorBrowsableState.Never)]
957 ClearDynamicResource = 1 << 2,
962 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
963 [EditorBrowsable(EditorBrowsableState.Never)]
964 RaiseOnEqual = 1 << 3