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);
88 internal void ListenPropertyChange(BindableProperty bindableProperty, PropertyChangedEventHandler eventHandler)
90 PropertyChangedListener propertyChangedListener;
91 BindablePropertyChangedEventDict.TryGetValue(bindableProperty.PropertyName, out propertyChangedListener);
93 if (null == propertyChangedListener)
95 propertyChangedListener = new PropertyChangedListener();
96 BindablePropertyChangedEventDict.Add(bindableProperty.PropertyName, propertyChangedListener);
99 propertyChangedListener.RegisterListnerHandler(eventHandler);
102 internal void RemovePropertyChangeListener(BindableProperty bindableProperty, PropertyChangedEventHandler propertyChangedEventHandler)
104 PropertyChangedListener propertyChangedListener;
105 BindablePropertyChangedEventDict.TryGetValue(bindableProperty.PropertyName, out propertyChangedListener);
107 if (null != propertyChangedListener)
109 propertyChangedListener.UnRegisterListnerHandler(propertyChangedEventHandler);
111 if (0 == propertyChangedListener.ListenerCount)
113 BindablePropertyChangedEventDict.Remove(bindableProperty.PropertyName);
118 private class PropertyChangedListener
120 internal void PropertyHasChanged(string propertyName)
122 PropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
125 internal void RegisterListnerHandler(PropertyChangedEventHandler propertyChangedEventHandler)
127 PropertyChanged += propertyChangedEventHandler;
131 internal void UnRegisterListnerHandler(PropertyChangedEventHandler propertyChangedEventHandler)
133 PropertyChanged -= propertyChangedEventHandler;
137 private int listenerCount = 0;
138 internal int ListenerCount
142 return listenerCount;
146 private event PropertyChangedEventHandler PropertyChanged;
149 private Dictionary<string, PropertyChangedListener> BindablePropertyChangedEventDict = new Dictionary<string, PropertyChangedListener>();
152 /// Raised whenever the BindingContext property changes.
154 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
155 [EditorBrowsable(EditorBrowsableState.Never)]
156 public event EventHandler BindingContextChanged;
158 internal void ClearValue(BindableProperty property, bool fromStyle)
160 ClearValue(property, fromStyle: fromStyle, checkAccess: true);
164 /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue.
166 /// <param name="property">The BindableProperty to clear</param>
167 internal void ClearValue(BindableProperty property)
169 ClearValue(property, fromStyle: false, checkAccess: true);
173 /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue for the property that is identified by propertyKey.
175 /// <param name="propertyKey">The BindablePropertyKey that identifies the BindableProperty to clear.</param>
176 internal void ClearValue(BindablePropertyKey propertyKey)
178 if (propertyKey == null)
179 throw new ArgumentNullException("propertyKey");
181 ClearValue(propertyKey.BindableProperty, fromStyle:false, checkAccess: false);
185 /// Return true if the target property exists and has been set.
187 /// <param name="targetProperty">The target property</param>
188 /// <returns>return true if the target property exists and has been set</returns>
189 internal bool IsSet(BindableProperty targetProperty)
191 if (targetProperty == null)
192 throw new ArgumentNullException(nameof(targetProperty));
194 var bpcontext = GetContext(targetProperty);
195 return bpcontext != null
196 && (bpcontext.Attributes & BindableContextAttributes.IsDefaultValue) == 0;
200 /// Returns the value that is contained the BindableProperty.
202 /// <param name="property">The BindableProperty for which to get the value.</param>
203 /// <returns>The value that is contained the BindableProperty</returns>
204 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
205 [EditorBrowsable(EditorBrowsableState.Never)]
206 public object GetValue(BindableProperty property)
208 if (property == null)
209 throw new ArgumentNullException("property");
211 BindablePropertyContext context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property);
214 return property.DefaultValue;
216 return context.Value;
220 /// Raised when a property is about to change.
222 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
223 [EditorBrowsable(EditorBrowsableState.Never)]
224 public event PropertyChangingEventHandler PropertyChanging;
227 /// Removes a previously set binding.
229 /// <param name="property">The BindableProperty from which to remove bindings.</param>
230 internal void RemoveBinding(BindableProperty property)
232 if (property == null)
233 throw new ArgumentNullException("property");
235 BindablePropertyContext context = GetContext(property);
236 if (context == null || context.Binding == null)
239 RemoveBinding(property, context);
243 /// Assigns a binding to a property.
245 /// <param name="targetProperty">The BindableProperty on which to set a binding.</param>
246 /// <param name="binding">The binding to set.</param>
247 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
248 [EditorBrowsable(EditorBrowsableState.Never)]
249 public void SetBinding(BindableProperty targetProperty, BindingBase binding)
251 SetBinding(targetProperty, binding, false);
254 private bool isCreateByXaml = false;
255 /// Only used by the IL of xaml, will never changed to not hidden.
256 [EditorBrowsable(EditorBrowsableState.Never)]
257 public virtual bool IsCreateByXaml
261 return isCreateByXaml;
265 isCreateByXaml = value;
270 /// Sets the value of the specified property.
272 /// <param name="property">The BindableProperty on which to assign a value.</param>
273 /// <param name="value">The value to set.</param>
274 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
275 [EditorBrowsable(EditorBrowsableState.Never)]
276 public void SetValue(BindableProperty property, object value)
278 if (true == isCreateByXaml)
280 SetValue(property, value, false, true);
284 property.PropertyChanged?.Invoke(this, null, value);
286 OnPropertyChanged(property.PropertyName);
288 if (BindablePropertyChangedEventDict.ContainsKey(property.PropertyName))
290 BindablePropertyChangedEventDict[property.PropertyName].PropertyHasChanged(property.PropertyName);
295 internal void SetValueAndForceSendChangeSignal(BindableProperty property, object value)
297 if (property == null)
298 throw new ArgumentNullException("property");
300 if (true == isCreateByXaml)
302 if (property.IsReadOnly)
303 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
305 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
306 SetValuePrivateFlags.ManuallySet | SetValuePrivateFlags.CheckAccess, true);
310 property.PropertyChanged?.Invoke(this, null, value);
315 /// Sets the value of the propertyKey.
317 /// <param name="propertyKey">The BindablePropertyKey on which to assign a value.</param>
318 /// <param name="value">The value to set.</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 public void SetValue(BindablePropertyKey propertyKey, object value)
323 if (propertyKey == null)
324 throw new ArgumentNullException("propertyKey");
326 SetValue(propertyKey.BindableProperty, value, false, false);
330 /// Set the inherited context to a neated element.
332 /// <param name="bindable">The object on which to set the inherited binding context.</param>
333 /// <param name="value">The inherited context to set.</param>
334 [EditorBrowsable(EditorBrowsableState.Never)]
335 public static void SetInheritedBindingContext(BindableObject bindable, object value)
337 BindablePropertyContext bpContext = bindable.GetContext(BindingContextProperty);
338 if (bpContext != null && ((bpContext.Attributes & BindableContextAttributes.IsManuallySet) != 0))
341 object oldContext = bindable._inheritedContext;
343 if (ReferenceEquals(oldContext, value))
346 if (bpContext != null && oldContext == null)
347 oldContext = bpContext.Value;
349 if (bpContext != null && bpContext.Binding != null)
351 bpContext.Binding.Context = value;
352 bindable._inheritedContext = null;
356 bindable._inheritedContext = value;
359 bindable.ApplyBindings(skipBindingContext:false, fromBindingContextChanged:true);
360 bindable.OnBindingContextChanged();
364 /// Apply the bindings to BindingContext.
366 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
367 [EditorBrowsable(EditorBrowsableState.Never)]
368 protected void ApplyBindings()
370 ApplyBindings(skipBindingContext: false, fromBindingContextChanged: false);
374 /// Override this method to execute an action when the BindingContext changes.
376 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
377 [EditorBrowsable(EditorBrowsableState.Never)]
378 protected virtual void OnBindingContextChanged()
380 BindingContextChanged?.Invoke(this, EventArgs.Empty);
384 /// Call this method from a child class to notify that a change happened on a property.
386 /// <param name="propertyName">The name of the property that changed.</param>
387 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
388 [EditorBrowsable(EditorBrowsableState.Never)]
389 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
390 => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
393 /// Call this method from a child class to notify that a change is going to happen on a property.
395 /// <param name="propertyName">The name of the property that is changing.</param>
396 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
397 [EditorBrowsable(EditorBrowsableState.Never)]
398 protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null)
399 => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
402 /// Unapplies all previously set bindings.
404 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
405 [EditorBrowsable(EditorBrowsableState.Never)]
406 protected void UnapplyBindings()
408 for (int i = 0, _propertiesCount = _properties.Count; i < _propertiesCount; i++) {
409 BindablePropertyContext context = _properties [i];
410 if (context.Binding == null)
413 context.Binding.Unapply();
417 internal bool GetIsBound(BindableProperty targetProperty)
419 if (targetProperty == null)
420 throw new ArgumentNullException("targetProperty");
422 BindablePropertyContext bpcontext = GetContext(targetProperty);
423 return bpcontext != null && bpcontext.Binding != null;
427 /// Returns the value that is contained the BindableProperty.
429 /// <param name="property0">The BindableProperty instance.</param>
430 /// <param name="property1">The BindableProperty instance.</param>
431 /// <returns>The value that is contained the BindableProperty</returns>
432 internal object[] GetValues(BindableProperty property0, BindableProperty property1)
434 var values = new object[2];
436 for (var i = 0; i < _properties.Count; i++)
438 BindablePropertyContext context = _properties[i];
440 if (ReferenceEquals(context.Property, property0))
442 values[0] = context.Value;
445 else if (ReferenceEquals(context.Property, property1))
447 values[1] = context.Value;
451 if (property0 == null && property1 == null)
455 if (!ReferenceEquals(property0, null))
456 values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
457 if (!ReferenceEquals(property1, null))
458 values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
464 /// Returns the value that is contained the BindableProperty.
466 /// <param name="property0">The BindableProperty instance.</param>
467 /// <param name="property1">The BindableProperty instance.</param>
468 /// <param name="property2">The BindableProperty instance.</param>
469 /// <returns>The value that is contained the BindableProperty</returns>
470 internal object[] GetValues(BindableProperty property0, BindableProperty property1, BindableProperty property2)
472 var values = new object[3];
474 for (var i = 0; i < _properties.Count; i++)
476 BindablePropertyContext context = _properties[i];
478 if (ReferenceEquals(context.Property, property0))
480 values[0] = context.Value;
483 else if (ReferenceEquals(context.Property, property1))
485 values[1] = context.Value;
488 else if (ReferenceEquals(context.Property, property2))
490 values[2] = context.Value;
494 if (property0 == null && property1 == null && property2 == null)
498 if (!ReferenceEquals(property0, null))
499 values[0] = property0.DefaultValueCreator == null ? property0.DefaultValue : CreateAndAddContext(property0).Value;
500 if (!ReferenceEquals(property1, null))
501 values[1] = property1.DefaultValueCreator == null ? property1.DefaultValue : CreateAndAddContext(property1).Value;
502 if (!ReferenceEquals(property2, null))
503 values[2] = property2.DefaultValueCreator == null ? property2.DefaultValue : CreateAndAddContext(property2).Value;
509 /// Returns the value that is contained the BindableProperty.
511 /// <param name="properties">The array of the BindableProperty instances</param>
512 /// <returns>The values that is contained the BindableProperty instances.</returns>
513 internal object[] GetValues(params BindableProperty[] properties)
515 var values = new object[properties.Length];
516 for (var i = 0; i < _properties.Count; i++) {
517 var context = _properties[i];
518 var index = properties.IndexOf(context.Property);
521 values[index] = context.Value;
523 for (var i = 0; i < values.Length; i++) {
524 if (!ReferenceEquals(values[i], null))
526 values[i] = properties[i].DefaultValueCreator == null ? properties[i].DefaultValue : CreateAndAddContext(properties[i]).Value;
531 internal virtual void OnRemoveDynamicResource(BindableProperty property)
535 internal virtual void OnSetDynamicResource(BindableProperty property, string key)
539 internal void RemoveDynamicResource(BindableProperty property)
541 if (property == null)
542 throw new ArgumentNullException("property");
544 OnRemoveDynamicResource(property);
545 BindablePropertyContext context = GetOrCreateContext(property);
546 context.Attributes &= ~BindableContextAttributes.IsDynamicResource;
549 internal void SetBinding(BindableProperty targetProperty, BindingBase binding, bool fromStyle)
551 if (targetProperty == null)
552 throw new ArgumentNullException("targetProperty");
554 throw new ArgumentNullException("binding");
556 if (fromStyle && !CanBeSetFromStyle(targetProperty))
559 var context = GetOrCreateContext(targetProperty);
561 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
563 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
565 if (context.Binding != null)
566 context.Binding.Unapply();
568 BindingBase oldBinding = context.Binding;
569 context.Binding = binding;
571 targetProperty.BindingChanging?.Invoke(this, oldBinding, binding);
573 binding.Apply(BindingContext, this, targetProperty);
576 bool CanBeSetFromStyle(BindableProperty property)
578 var context = GetContext(property);
581 if ((context.Attributes & BindableContextAttributes.IsSetFromStyle) == BindableContextAttributes.IsSetFromStyle)
583 if ((context.Attributes & BindableContextAttributes.IsDefaultValue) == BindableContextAttributes.IsDefaultValue)
585 if ((context.Attributes & BindableContextAttributes.IsDefaultValueCreated) == BindableContextAttributes.IsDefaultValueCreated)
590 internal void SetDynamicResource(BindableProperty property, string key)
592 SetDynamicResource(property, key, false);
595 internal void SetDynamicResource(BindableProperty property, string key, bool fromStyle)
597 if (property == null)
598 throw new ArgumentNullException(nameof(property));
599 if (string.IsNullOrEmpty(key))
600 throw new ArgumentNullException(nameof(key));
601 if (fromStyle && !CanBeSetFromStyle(property))
604 var context = GetOrCreateContext(property);
606 context.Attributes |= BindableContextAttributes.IsDynamicResource;
608 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
610 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
612 OnSetDynamicResource(property, key);
615 internal void SetValue(BindableProperty property, object value, bool fromStyle)
617 SetValue(property, value, fromStyle, true);
620 internal void SetValueCore(BindablePropertyKey propertyKey, object value, SetValueFlags attributes = SetValueFlags.None)
622 SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None, false);
626 /// For internal use.
628 /// <param name="property">The BindableProperty on which to assign a value.</param>
629 /// <param name="value">The value to set</param>
630 /// <param name="attributes">The set value flag</param>
631 [EditorBrowsable(EditorBrowsableState.Never)]
632 internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None)
634 SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, false);
637 internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, bool forceSendChangeSignal)
639 bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
640 bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
641 bool silent = (privateAttributes & SetValuePrivateFlags.Silent) != 0;
642 bool fromStyle = (privateAttributes & SetValuePrivateFlags.FromStyle) != 0;
643 bool converted = (privateAttributes & SetValuePrivateFlags.Converted) != 0;
645 if (property == null)
646 throw new ArgumentNullException("property");
647 if (checkAccess && property.IsReadOnly)
649 Debug.WriteLine("Can not set the BindableProperty \"{0}\" because it is readonly.", property.PropertyName);
653 if (!converted && !property.TryConvert(ref value))
655 Console.WriteLine("SetValue", "Can not convert {0} to type '{1}'", value, property.ReturnType);
659 if (property.ValidateValue != null && !property.ValidateValue(this, value))
660 throw new ArgumentException("Value was an invalid value for " + property.PropertyName, "value");
662 if (property.CoerceValue != null)
663 value = property.CoerceValue(this, value);
665 BindablePropertyContext context = GetOrCreateContext(property);
667 context.Attributes |= BindableContextAttributes.IsManuallySet;
668 context.Attributes &= ~BindableContextAttributes.IsSetFromStyle;
670 context.Attributes &= ~BindableContextAttributes.IsManuallySet;
673 context.Attributes |= BindableContextAttributes.IsSetFromStyle;
674 // else omitted on purpose
676 bool currentlyApplying = _applying;
678 if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
680 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
681 if (delayQueue == null)
682 context.DelayedSetters = delayQueue = new Queue<SetValueArgs>();
684 delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
688 context.Attributes |= BindableContextAttributes.IsBeingSet;
689 SetValueActual(property, context, value, currentlyApplying, forceSendChangeSignal, attributes, silent);
691 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
692 if (delayQueue != null)
694 while (delayQueue.Count > 0)
696 SetValueArgs s = delayQueue.Dequeue();
697 SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, forceSendChangeSignal, s.Attributes);
700 context.DelayedSetters = null;
703 context.Attributes &= ~BindableContextAttributes.IsBeingSet;
707 internal void ApplyBindings(bool skipBindingContext, bool fromBindingContextChanged)
709 var prop = _properties.ToArray();
710 for (int i = 0, propLength = prop.Length; i < propLength; i++) {
711 BindablePropertyContext context = prop [i];
712 BindingBase binding = context.Binding;
716 if (skipBindingContext && ReferenceEquals(context.Property, BindingContextProperty))
719 binding.Unapply(fromBindingContextChanged: fromBindingContextChanged);
720 binding.Apply(BindingContext, this, context.Property, fromBindingContextChanged: fromBindingContextChanged);
724 static void BindingContextPropertyBindingChanging(BindableObject bindable, BindingBase oldBindingBase, BindingBase newBindingBase)
726 object context = bindable._inheritedContext;
727 var oldBinding = oldBindingBase as Binding;
728 var newBinding = newBindingBase as Binding;
730 if (context == null && oldBinding != null)
731 context = oldBinding.Context;
732 if (context != null && newBinding != null)
733 newBinding.Context = context;
736 static void BindingContextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
738 bindable._inheritedContext = null;
739 bindable.ApplyBindings(skipBindingContext: true, fromBindingContextChanged:true);
740 bindable.OnBindingContextChanged();
743 void ClearValue(BindableProperty property, bool fromStyle, bool checkAccess)
745 if (property == null)
746 throw new ArgumentNullException(nameof(property));
748 if (checkAccess && property.IsReadOnly)
749 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
751 BindablePropertyContext bpcontext = GetContext(property);
752 if (bpcontext == null)
755 if (fromStyle && !CanBeSetFromStyle(property))
758 object original = bpcontext.Value;
760 object newValue = property.GetDefaultValue(this);
762 bool same = Equals(original, newValue);
765 property.PropertyChanging?.Invoke(this, original, newValue);
767 OnPropertyChanging(property.PropertyName);
770 bpcontext.Attributes &= ~BindableContextAttributes.IsManuallySet;
771 bpcontext.Value = newValue;
772 if (property.DefaultValueCreator == null)
773 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValue;
775 bpcontext.Attributes |= BindableContextAttributes.IsDefaultValueCreated;
779 OnPropertyChanged(property.PropertyName);
780 property.PropertyChanged?.Invoke(this, original, newValue);
784 [MethodImpl(MethodImplOptions.AggressiveInlining)]
785 BindablePropertyContext CreateAndAddContext(BindableProperty property)
787 var context = new BindablePropertyContext { Property = property, Value = property.DefaultValueCreator != null ? property.DefaultValueCreator(this) : property.DefaultValue };
789 if (property.DefaultValueCreator == null)
790 context.Attributes = BindableContextAttributes.IsDefaultValue;
792 context.Attributes = BindableContextAttributes.IsDefaultValueCreated;
794 _properties.Add(context);
798 [MethodImpl(MethodImplOptions.AggressiveInlining)]
799 BindablePropertyContext GetContext(BindableProperty property)
801 List<BindablePropertyContext> properties = _properties;
803 for (var i = 0; i < properties.Count; i++)
805 BindablePropertyContext context = properties[i];
806 if (ReferenceEquals(context.Property, property))
813 [MethodImpl(MethodImplOptions.AggressiveInlining)]
814 BindablePropertyContext GetOrCreateContext(BindableProperty property)
816 BindablePropertyContext context = GetContext(property);
819 context = CreateAndAddContext(property);
821 else if (property.DefaultValueCreator != null )
823 context.Value = property.DefaultValueCreator(this); //Update Value from dali
829 void RemoveBinding(BindableProperty property, BindablePropertyContext context)
831 context.Binding.Unapply();
833 property.BindingChanging?.Invoke(this, context.Binding, null);
835 context.Binding = null;
838 void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
840 if (property == null)
841 throw new ArgumentNullException("property");
843 if (checkAccess && property.IsReadOnly)
844 throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
846 if (fromStyle && !CanBeSetFromStyle(property))
849 SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
850 (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0),
854 void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, bool forceSendChangeSignal, SetValueFlags attributes, bool silent = false)
856 object original = context.Value;
857 bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0;
858 bool clearDynamicResources = (attributes & SetValueFlags.ClearDynamicResource) != 0;
859 bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0;
860 bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0;
862 bool same = ReferenceEquals(context.Property, BindingContextProperty) ? ReferenceEquals(value, original) : Equals(value, original);
863 if (!silent && (!same || raiseOnEqual))
865 property.PropertyChanging?.Invoke(this, original, value);
867 OnPropertyChanging(property.PropertyName);
870 if (!same || raiseOnEqual)
872 context.Value = value;
875 context.Attributes &= ~BindableContextAttributes.IsDefaultValue;
876 context.Attributes &= ~BindableContextAttributes.IsDefaultValueCreated;
878 if ((context.Attributes & BindableContextAttributes.IsDynamicResource) != 0 && clearDynamicResources)
879 RemoveDynamicResource(property);
881 BindingBase binding = context.Binding;
884 if (clearOneWayBindings && binding.GetRealizedMode(property) == BindingMode.OneWay || clearTwoWayBindings && binding.GetRealizedMode(property) == BindingMode.TwoWay)
886 RemoveBinding(property, context);
893 if ((!same || raiseOnEqual))
895 property.PropertyChanged?.Invoke(this, original, value);
897 if (binding != null && !currentlyApplying)
904 OnPropertyChanged(property.PropertyName);
906 else if (true == same && true == forceSendChangeSignal)
908 if (binding != null && !currentlyApplying)
915 OnPropertyChanged(property.PropertyName);
921 enum BindableContextAttributes
923 IsManuallySet = 1 << 0,
925 IsDynamicResource = 1 << 2,
926 IsSetFromStyle = 1 << 3,
927 IsDefaultValue = 1 << 4,
928 IsDefaultValueCreated = 1 << 5,
931 class BindablePropertyContext
933 public BindableContextAttributes Attributes;
934 public BindingBase Binding;
935 public Queue<SetValueArgs> DelayedSetters;
936 public BindableProperty Property;
941 internal enum SetValuePrivateFlags
944 CheckAccess = 1 << 0,
946 ManuallySet = 1 << 2,
949 Default = CheckAccess
954 public readonly SetValueFlags Attributes;
955 public readonly BindablePropertyContext Context;
956 public readonly bool CurrentlyApplying;
957 public readonly BindableProperty Property;
958 public readonly object Value;
960 public SetValueArgs(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes)
965 CurrentlyApplying = currentlyApplying;
966 Attributes = attributes;
972 namespace Tizen.NUI.Binding.Internals
975 /// SetValueFlags. For internal use.
978 [EditorBrowsable(EditorBrowsableState.Never)]
979 public enum SetValueFlags
984 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
985 [EditorBrowsable(EditorBrowsableState.Never)]
989 /// Clear OneWay bindings.
991 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
992 [EditorBrowsable(EditorBrowsableState.Never)]
993 ClearOneWayBindings = 1 << 0,
996 /// Clear TwoWay bindings.
998 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
999 [EditorBrowsable(EditorBrowsableState.Never)]
1000 ClearTwoWayBindings = 1 << 1,
1003 /// Clear dynamic resource.
1005 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
1006 [EditorBrowsable(EditorBrowsableState.Never)]
1007 ClearDynamicResource = 1 << 2,
1012 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
1013 [EditorBrowsable(EditorBrowsableState.Never)]
1014 RaiseOnEqual = 1 << 3