示例#1
0
        public static object GetValue(INTERNAL_PropertyStorage storage, PropertyMetadata typeMetadata)
        {
#if PERFSTAT
            var t = Performance.now();
#endif
            object returnValue;

            if (storage == null)
            {
                //===================
                // NO STORAGE EXISTS:
                //===================

                // Return the default value:
                returnValue = typeMetadata != null ? typeMetadata.DefaultValue : null;
            }
            else
            {
                //====================
                // THE STORAGE EXISTS:
                //====================

                return(storage.ActualValue);
            }

#if PERFSTAT
            Performance.Counter("INTERNAL_PropertyStore.GetValue", t);
#endif

            return(returnValue);
        }
        private static object GetCoercionBaseValue(INTERNAL_PropertyStorage storage)
        {
            object baseValue;

            if (!storage.HasModifiers)
            {
                baseValue = storage.Value;
            }
            else if (storage.IsCoerced)
            {
                if (storage.IsCoercedWithCurrentValue)
                {
                    baseValue = storage.ModifiedValue.CoercedValue;
                }
                else if (storage.IsExpression /* || storage.IsExpressionFromStyle*/)
                {
                    baseValue = storage.ModifiedValue.ExpressionValue;
                }
                else
                {
                    //global::System.Diagnostics.Debug.Assert(!storage.IsExpressionFromStyle);
                    // Only modifier is Coerced
                    baseValue = storage.ModifiedValue.BaseValue;
                }
            }
            else
            {
                global::System.Diagnostics.Debug.Assert(storage.IsExpression /* || storage.IsExpressionFromStyle*/);
                baseValue = storage.ModifiedValue.ExpressionValue;
            }
            return(baseValue);
        }
        private static void OnPropertyChanged(INTERNAL_PropertyStorage storage, object oldValue, object newValue)
        {
            DependencyObject sender = storage.Owner;

            var typeMetadata = storage.TypeMetadata;

            //---------------------
            // Ensure tha the value knows in which properties it is used (this is useful for example so that a SolidColorBrush knows in which properties it is used):
            //---------------------

            if (oldValue is IHasAccessToPropertiesWhereItIsUsed)
            {
                ((IHasAccessToPropertiesWhereItIsUsed)oldValue).PropertiesWhereUsed.Remove(new KeyValuePair <DependencyObject, DependencyProperty>(sender, storage.Property));
            }

            if (newValue is IHasAccessToPropertiesWhereItIsUsed)
            {
                IHasAccessToPropertiesWhereItIsUsed newValueAsIHasAccessToPropertiesWhereItIsUsed = (IHasAccessToPropertiesWhereItIsUsed)newValue;
                // Note: it is not supposed to happen that the element is already in the list.
                newValueAsIHasAccessToPropertiesWhereItIsUsed.PropertiesWhereUsed.Add(new KeyValuePair <DependencyObject, DependencyProperty>(sender, storage.Property));
            }

            //---------------------
            // If the element is in the Visual Tree, update the DOM:
            //---------------------

            if (typeMetadata != null)
            {
                ApplyCssChanges(oldValue, newValue, typeMetadata, sender); // Note: this we need to call regardless of whether the element is in the visual tree. In fact, for example, the SolidColorBrush.Color property can be used by multiple UIElements, some of which may be in the visual tree and others not.

                if (sender is UIElement && ((UIElement)sender)._isLoaded)
                {
                    if (typeMetadata.MethodToUpdateDom != null)
                    {
                        typeMetadata.MethodToUpdateDom(sender, newValue); // Note: this we call only if the element is in the visual tree.
                    }
                }
            }

            //---------------------
            // Call the PropertyChangedCallback if any:
            //---------------------

            if (typeMetadata != null && typeMetadata.PropertyChangedCallback != null)
            {
                typeMetadata.PropertyChangedCallback(sender, new DependencyPropertyChangedEventArgs(oldValue, newValue, storage.Property));
            }

            //---------------------
            // Update bindings if any:
            //---------------------

            if (storage.PropertyListeners != null)
            {
                foreach (IPropertyChangedListener listener in storage.PropertyListeners)
                {
                    listener.OnPropertyChanged(sender, new DependencyPropertyChangedEventArgs(oldValue, newValue, storage.Property));
                }
            }
        }
        static void RaisePropertyChangedAndCascadeToChildren(INTERNAL_PropertyStorage storage, object oldValue, object newValue, PropertyMetadata typeMetadata)
        {
            //-----------------------
            // CHECK IF THE PROPERTY BELONGS TO THE OBJECT (OR TO ONE OF ITS ANCESTORS):
            //-----------------------
            if (ShouldRaisePropertyChanged(storage))
            {
                // Raise Property Changed:
                OnPropertyChanged(storage, oldValue, newValue, typeMetadata: typeMetadata);
            }

            //-----------------------
            // CHECK IF THE PROPERTY IS INHERITABLE:
            //-----------------------
            if (typeMetadata == null)
            {
                typeMetadata = storage.Property.GetTypeMetaData(storage.Owner.GetType());
            }
            if (typeMetadata != null && typeMetadata.Inherits)
            {
                //-----------------------
                // PROPAGATE TO CHILDREN:
                //-----------------------
                CascadeInheritedPropertyToChildren(storage, newValue);

                HandleSpecialPropertiesThatShouldInheritDataContext(storage, newValue);
            }
        }
 private static bool ShouldRaisePropertyChanged(INTERNAL_PropertyStorage storage)
 {
     // Note: we only want to call "OnPropertyChanged" when the property is used by the current DependencyObject or if it is the DataContext property.
     if (!storage.Property.IsAttached)
     {
         return(storage.Property.OwnerType.IsAssignableFrom(storage.Owner.GetType()) || storage.Property == FrameworkElement.DataContextProperty);
     }
     return(true);
 }
        //about the todo below, make sure we don't want a specific value to purposely set it at null
        public static object GetValue(INTERNAL_PropertyStorage storage, PropertyMetadata typeMetadata = null) //todo: remove the "(value = storage.Local) != null" because the user might purposely set it at null OR define a specific value to purposely set something at null
        {
#if PERFSTAT
            var t = Performance.now();
#endif
            object value;
            if (storage._isIsEnabledOrIsHitTestVisibleProperty)
            {
                if ((value = storage.InheritedValue) != INTERNAL_NoValue.NoValue && value != null && ((bool)value) == false)
                {
#if PERFSTAT
                    Performance.Counter("INTERNAL_PropertyStore.GetValue", t);
#endif
                    return(false);
                }
            }

            //todo: remove all comparisons with "null" to leave only the comparisons with "NoValue":
            if ((value = storage.CoercedValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((value = storage.VisualStateValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if (storage.ActiveLocalValue.ActiveValue == KindOfValue.Local && (value = storage.Local) != INTERNAL_NoValue.NoValue)
            {
            }
            else if (storage.ActiveLocalValue.ActiveValue == KindOfValue.Animated && (value = storage.AnimationValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((value = storage.LocalStyleValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((value = storage.ImplicitStyleValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((value = storage.InheritedValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else
            {
                if (typeMetadata == null)
                {
                    typeMetadata = storage.Property.GetTypeMetaData(storage.Owner.GetType());
                }
#if PERFSTAT
                Performance.Counter("INTERNAL_PropertyStore.GetValue", t);
#endif
                return(typeMetadata != null ? typeMetadata.DefaultValue : null);
            }

#if PERFSTAT
            Performance.Counter("INTERNAL_PropertyStore.GetValue", t);
#endif
            return(value);
        }
示例#7
0
 internal static void HandleSpecialPropertiesThatShouldInheritDataContext(INTERNAL_PropertyStorage storage, object newValue)
 {
     // Support inheriting the DataContext in other properties such as "RenderTransform", which does not happen automatically because Transforms are not FrameworkElements so they are not in the visual tree (they are not in the "VisualChildren" internal collection). This ensures that, for example, <RotateTransform Angle="{Binding=Angle}"/> work properly:
     if ((storage.Owner is UIElement) &&
         (storage.Owner as UIElement).RenderTransform != null &&
         storage.Property == FrameworkElement.DataContextProperty)
     {
         (storage.Owner as UIElement).RenderTransform.SetInheritedValue(FrameworkElement.DataContextProperty, newValue, recursively: false);
     }
 }
示例#8
0
        internal static void ResetInheritedValue(INTERNAL_PropertyStorage storage)
        {
            storage.InheritedValue = DependencyProperty.UnsetValue;

            //UpdateEffectiveValue(storage,
            //                     DependencyProperty.UnsetValue,
            //                     BaseValueSourceInternal.Inherited,
            //                     false, // coerceWithCurrentValue
            //                     false, // coerceValue
            //                     true, // clearValue
            //                     false); // propagateChanges
        }
        internal static void SetImplicitReferenceValue(INTERNAL_PropertyStorage storage, object newValue)
        {
            storage.ImplicitReferenceValue = newValue;

            UpdateEffectiveValue(storage,
                                 newValue,
                                 BaseValueSourceInternal.ImplicitReference,
                                 false,                                     // coerceWithCurrentValue
                                 false,                                     // coerceValue
                                 newValue == DependencyProperty.UnsetValue, // clearValue
                                 true);                                     // propagateChanges
        }
        internal static void SetInheritedValue(INTERNAL_PropertyStorage storage, object newValue, bool recursively)
        {
            storage.InheritedValue = newValue;

            UpdateEffectiveValue(storage,
                                 newValue,
                                 BaseValueSourceInternal.Inherited,
                                 false,                                     // coerceWithCurrentValue
                                 false,                                     // coerceValue
                                 newValue == DependencyProperty.UnsetValue, // clearValue
                                 recursively);                              // propagateChanges
        }
        internal static void SetValueCommon(INTERNAL_PropertyStorage storage,
                                            object newValue,
                                            bool coerceWithCurrentValue)
        {
            if (newValue == DependencyProperty.UnsetValue)
            {
                global::System.Diagnostics.Debug.Assert(!coerceWithCurrentValue, "Don't call SetCurrentValue with UnsetValue");
                ClearValueCommon(storage);
                return;
            }

            if (!coerceWithCurrentValue)
            {
                object newLocalValue = newValue;

                if (storage.BaseValueSourceInternal == BaseValueSourceInternal.Local)
                {
                    BindingExpression currentExpr = storage.LocalValue as BindingExpression;
                    if (currentExpr != null)
                    {
                        BindingExpression newExpr = newValue as BindingExpression;
                        if (currentExpr == newExpr)
                        {
                            global::System.Diagnostics.Debug.Assert(newExpr.IsAttached);
                            RefreshBindingExpressionCommon(storage, newExpr);
                            return;
                        }

                        // if the current BindingExpression is a TwoWay binding, we don't want to remove the binding
                        // unless we are overriding it with a new BindingExpression.
                        if (newExpr != null || currentExpr.ParentBinding.Mode != BindingMode.TwoWay)
                        {
                            currentExpr.OnDetached(storage.Owner);
                        }
                        else
                        {
                            newLocalValue = currentExpr;
                        }
                    }
                }

                // Set the new local value
                storage.LocalValue = newLocalValue;
            }

            UpdateEffectiveValue(storage,
                                 newValue,
                                 BaseValueSourceInternal.Local,
                                 coerceWithCurrentValue, // coerceWithCurrentValue
                                 false,                  // coerceValue
                                 false,                  // clearValue
                                 true);                  // propagateChanges
        }
        internal static void SetInheritedValue(INTERNAL_PropertyStorage storage, object newValue, bool recursively) //the "firePropertyChangedEvent" parameter allows us to only throw the onPropertyChangedEvent when the dependencyObject actually uses the property that is changed.
        {
            bool             impactsActualValue = DoesSpecificValueImpactActualValue(storage, KindOfValue.Inherited);
            PropertyMetadata typeMetadata       = storage.Property.GetTypeMetaData(storage.Owner.GetType());
            object           oldValue           = GetValue(storage, typeMetadata);

            storage.InheritedValue = newValue;

            //-----------------------
            // CHECK THAT A LOCAL OR STYLE VALUE DOES NOT EXIST (otherwise the local/style values superset the inherited value, and we don't want to raise PropertyChanged, nor continue the recursion)
            //-----------------------
            if (impactsActualValue)
            {
                object actualNewValue  = GetValueWithoutCoerce(storage, typeMetadata);
                object coercedNewValue = ((typeMetadata != null && typeMetadata.CoerceValueCallback != null) ? typeMetadata.CoerceValueCallback(storage.Owner, actualNewValue) : actualNewValue);
                //-----------------------
                // CHECK IF THE PROPERTY BELONGS TO THE OBJECT (OR TO ONE OF ITS ANCESTORS):
                //-----------------------
                //we only do the following inside the "if" because otherwise, the children's inherithed property would not change anyway
                if (oldValue != coercedNewValue)
                {
                    if (ShouldRaisePropertyChanged(storage))
                    {
                        OnPropertyChanged(storage, oldValue, coercedNewValue, typeMetadata: typeMetadata);
                    }
                    if (recursively)
                    {
                        CascadeInheritedPropertyToChildren(storage, coercedNewValue);
                    }

                    HandleSpecialPropertiesThatShouldInheritDataContext(storage, coercedNewValue);
                }
            }
            else if (storage._isIsEnabledOrIsHitTestVisibleProperty) //todo: if we decide to make coercion possible on IsHitTestVisible or IsEnabled, change the "newValue" below into "coercedNewValue" (probably)
            {
                if (((bool)newValue == true))
                {
                    newValue = GetValue(GetStorage(storage.Owner, storage.Property)); //we need newValue to be the value that will be active afterwards.
                }
                if (oldValue != newValue)
                {
                    if (ShouldRaisePropertyChanged(storage))
                    {
                        OnPropertyChanged(storage, oldValue, newValue, typeMetadata: typeMetadata);
                    }
                    if (recursively)
                    {
                        CascadeInheritedPropertyToChildren(storage, newValue);
                    }
                }
            }
        }
        internal static void RefreshBindingExpressionCommon(INTERNAL_PropertyStorage storage, BindingExpression expression)
        {
            global::System.Diagnostics.Debug.Assert(expression != null, "Expression should not be null");
            global::System.Diagnostics.Debug.Assert(storage.IsExpression || storage.IsExpressionFromStyle, "Property base value is not a BindingExpression !");

            UpdateEffectiveValue(storage,
                                 expression,
                                 expression.ParentBinding._isInStyle ? BaseValueSourceInternal.LocalStyle : BaseValueSourceInternal.Local,
                                 false, // coerceWithCurrentValue
                                 false, // coerceValue
                                 false, // clearValue
                                 true); // propagateChanges
        }
 internal static object GetEffectiveValue(INTERNAL_PropertyStorage storage)
 {
     if (storage.HasModifiers)
     {
         return((storage.IsCoercedWithCurrentValue || storage.IsCoerced)
                ? storage.ModifiedValue.CoercedValue
                : storage.ModifiedValue.ExpressionValue);
     }
     else
     {
         return(storage.Value);
     }
 }
示例#15
0
        internal static void CoerceCurrentValue(INTERNAL_PropertyStorage storage)
        {
            var typeMetadata = storage.TypeMetadata;

            if (typeMetadata == null || typeMetadata.CoerceValueCallback == null)
            {
                return; //we should not arrive here in this case but we make sure to not do anything should that happen.
            }
            object oldValue        = storage.Local == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.Local;
            object currentValue    = ComputeActualValue(storage, typeMetadata, true); //Note: we do not need to know where this value comes from (Local, VisualState, etc.) since calling this method means that it has not been modified and we only need to update the coerced value.
            object coercedNewValue = typeMetadata.CoerceValueCallback(storage.Owner, currentValue);

            SetSpecificValue(storage, KindOfValue.Coerced, coercedNewValue);
        }
示例#16
0
        static bool DoesSpecificValueImpactActualValue(INTERNAL_PropertyStorage storage, KindOfValue kind)
        {
            object value;

            //Note: in KindOfValue, the value attributed to the enum values corresponds to their priority rank so the lower, the more priority.
            if ((kind <= KindOfValue.VisualState || ((value = storage.VisualStateValue) == INTERNAL_NoValue.NoValue)) && //means "kind has a higher priority tha VisualState or there is no VisualState value
                (kind <= KindOfValue.Local || ((value = storage.Local) == INTERNAL_NoValue.NoValue)) &&
                (kind <= KindOfValue.LocalStyle || ((value = storage.LocalStyleValue) == INTERNAL_NoValue.NoValue)) &&
                (kind <= KindOfValue.ImplicitStyle || ((value = storage.ImplicitStyleValue) == INTERNAL_NoValue.NoValue)) &&
                (kind <= KindOfValue.Inherited || ((value = storage.InheritedValue) == INTERNAL_NoValue.NoValue)))
            {
                return(true);
            }
            return(false);
        }
        private static void CascadeInheritedPropertyToChildren(INTERNAL_PropertyStorage storage, object newValue)
        {
            DependencyObject dependencyObject = storage.Owner;

            // Set Inherited Value on the children:
            if (dependencyObject is UIElement parentUIE)
            {
                if (parentUIE.INTERNAL_VisualChildrenInformation != null)
                {
                    foreach (UIElement child in parentUIE.INTERNAL_VisualChildrenInformation.Keys) //all the children should be in there
                    {
                        child.SetInheritedValue(storage.Property, newValue, true);
                    }
                }
            }
        }
        internal static void CoerceValueCommon(INTERNAL_PropertyStorage storage)
        {
            if (storage.IsCoercedWithCurrentValue)
            {
                SetValueCommon(storage, storage.ModifiedValue.CoercedValue, true);
                return;
            }

            UpdateEffectiveValue(storage,
                                 null,  //unused for coerce operation
                                 BaseValueSourceInternal.Local,
                                 false, // coerceWithCurrentValue
                                 true,  // coerceValue
                                 false, // clearValue
                                 true); // propagateChanges
        }
示例#19
0
        public static INTERNAL_PropertyStorage GetStorageOrCreateNewIfNotExists(DependencyObject dependencyObject, DependencyProperty dependencyProperty)
        {
            // Check if the storage exists:
            INTERNAL_PropertyStorage storage;

            if (dependencyObject.INTERNAL_PropertyStorageDictionary == null ||
                !dependencyObject.INTERNAL_PropertyStorageDictionary.TryGetValue(dependencyProperty, out storage))
            {
                // Create the dictionary of it does not already exist:
                if (dependencyObject.INTERNAL_PropertyStorageDictionary == null)
                {
                    dependencyObject.INTERNAL_PropertyStorageDictionary = new Dictionary <DependencyProperty, INTERNAL_PropertyStorage>();
                }

                // Get the type metadata (if any):
                PropertyMetadata typeMetadata = dependencyProperty.GetTypeMetaData(dependencyObject.GetType());

                //----------------------
                // CREATE A NEW STORAGE:
                //----------------------

                storage = new INTERNAL_PropertyStorage(dependencyObject, dependencyProperty, typeMetadata);
                dependencyObject.INTERNAL_PropertyStorageDictionary.Add(dependencyProperty, storage);

                //-----------------------
                // CHECK IF THE PROPERTY IS INHERITABLE:
                //-----------------------
                if (typeMetadata != null && typeMetadata.Inherits)
                {
                    //-----------------------
                    // ADD THE STORAGE TO "INTERNAL_AllInheritedProperties" IF IT IS NOT ALREADY THERE:
                    //-----------------------
                    if (dependencyObject.INTERNAL_AllInheritedProperties == null)
                    {
                        dependencyObject.INTERNAL_AllInheritedProperties = new Dictionary <DependencyProperty, INTERNAL_PropertyStorage>();
                    }

                    if (!dependencyObject.INTERNAL_AllInheritedProperties.ContainsKey(dependencyProperty))
                    {
                        dependencyObject.INTERNAL_AllInheritedProperties.Add(dependencyProperty, storage);
                    }
                }
            }

            return(storage);
        }
        public static INTERNAL_PropertyStorage GetStorage(DependencyObject dependencyObject, DependencyProperty dependencyProperty, bool createAndSaveNewStorageIfNotExists = false)
        {
            // Create the dictionary of it does not already exist:
            if (dependencyObject.INTERNAL_PropertyStorageDictionary == null)
            {
                dependencyObject.INTERNAL_PropertyStorageDictionary = new Dictionary <DependencyProperty, INTERNAL_PropertyStorage>();
            }

            // Create the Storage if it does not already exist, and if "createAndSaveNewStorageIfNotExists" is True:
            INTERNAL_PropertyStorage storage;

            if (!dependencyObject.INTERNAL_PropertyStorageDictionary.TryGetValue(dependencyProperty, out storage))
            {
                storage = new INTERNAL_PropertyStorage(dependencyObject, dependencyProperty);
                if (createAndSaveNewStorageIfNotExists)
                {
                    dependencyObject.INTERNAL_PropertyStorageDictionary.Add(dependencyProperty, storage);

                    //-----------------------
                    // CHECK IF THE PROPERTY IS INHERITABLE:
                    //-----------------------
                    PropertyMetadata typeMetadata = storage.Property.GetTypeMetaData(storage.Owner.GetType());
                    if (typeMetadata != null && typeMetadata.Inherits)
                    {
                        //-----------------------
                        // ADD THE STORAGE TO "INTERNAL_AllInheritedProperties" IF IT IS NOT ALREADY THERE:
                        //-----------------------
                        if (dependencyObject.INTERNAL_AllInheritedProperties == null)
                        {
                            dependencyObject.INTERNAL_AllInheritedProperties = new Dictionary <DependencyProperty, INTERNAL_PropertyStorage>();
                        }

                        if (!dependencyObject.INTERNAL_AllInheritedProperties.ContainsKey(dependencyProperty))
                        {
                            dependencyObject.INTERNAL_AllInheritedProperties.Add(dependencyProperty, storage);
                        }
                    }
                }
            }

            return(storage);
        }
 private static void ComputeEffectiveValue(INTERNAL_PropertyStorage storage,
                                           out object effectiveValue,
                                           out BaseValueSourceInternal kind)
 {
     if (!storage.IsAnimatedOverLocal &&
         storage.LocalValue != DependencyProperty.UnsetValue)
     {
         effectiveValue = storage.LocalValue;
         kind           = BaseValueSourceInternal.Local;
     }
     else if (storage.IsAnimatedOverLocal &&
              storage.AnimatedValue != DependencyProperty.UnsetValue)
     {
         effectiveValue = storage.AnimatedValue;
         kind           = BaseValueSourceInternal.Animated;
     }
     else if (storage.ImplicitReferenceValue != DependencyProperty.UnsetValue)
     {
         effectiveValue = storage.ImplicitReferenceValue;
         kind           = BaseValueSourceInternal.ImplicitReference;
     }
     else if (storage.LocalStyleValue != DependencyProperty.UnsetValue)
     {
         effectiveValue = storage.LocalStyleValue;
         kind           = BaseValueSourceInternal.LocalStyle;
     }
     else if (storage.ThemeStyleValue != DependencyProperty.UnsetValue)
     {
         effectiveValue = storage.ThemeStyleValue;
         kind           = BaseValueSourceInternal.ThemeStyle;
     }
     else if (storage.InheritedValue != DependencyProperty.UnsetValue)
     {
         effectiveValue = storage.InheritedValue;
         kind           = BaseValueSourceInternal.Inherited;
     }
     else // Property default value
     {
         effectiveValue = storage.TypeMetadata.DefaultValue;
         kind           = BaseValueSourceInternal.Default;
     }
 }
        private static void ProcessCoerceValue(INTERNAL_PropertyStorage storage,
                                               ref object newValue,
                                               object oldValue,
                                               object baseValue,
                                               bool coerceWithCurrentValue)
        {
            newValue = coerceWithCurrentValue ? newValue : storage.TypeMetadata.CoerceValueCallback(storage.Owner, newValue);

            if (!ArePropertiesEqual(newValue, baseValue, storage.Property.PropertyType))
            {
                // returning DependencyProperty.UnsetValue from a Coercion callback means "don't do the set" ...
                // or "use previous value"
                if (newValue == DependencyProperty.UnsetValue)
                {
                    newValue = oldValue;
                }

                storage.SetCoercedValue(newValue, baseValue, coerceWithCurrentValue);
            }
        }
示例#23
0
        public static object ComputeActualValue(INTERNAL_PropertyStorage storage, PropertyMetadata typeMetadata, bool ignoreCoercedValue)
        {
            object actualValue;

            if (storage._isIsEnabledOrIsHitTestVisibleProperty)
            {
                if ((actualValue = storage.InheritedValue) != INTERNAL_NoValue.NoValue && actualValue != null && ((bool)actualValue) == false)
                {
                    return(false);
                }
            }

            if (!ignoreCoercedValue && (actualValue = storage.CoercedValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((actualValue = storage.VisualStateValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if (storage.ActiveLocalValue.ActiveValue == KindOfValue.Local && (actualValue = storage.Local) != INTERNAL_NoValue.NoValue)
            {
            }
            else if (storage.ActiveLocalValue.ActiveValue == KindOfValue.Animated && (actualValue = storage.AnimationValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((actualValue = storage.LocalStyleValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((actualValue = storage.ImplicitStyleValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else if ((actualValue = storage.InheritedValue) != INTERNAL_NoValue.NoValue)
            {
            }
            else
            {
                // Return the default value:
                actualValue = typeMetadata != null ? typeMetadata.DefaultValue : null;
            }

            return(actualValue);
        }
        internal static void SetThemeStyleValue(INTERNAL_PropertyStorage storage, object newValue)
        {
            if (storage.BaseValueSourceInternal == BaseValueSourceInternal.ThemeStyle)
            {
                BindingExpression oldExpr = storage.IsExpressionFromStyle ? storage.ThemeStyleValue as BindingExpression : null;
                if (oldExpr != null)
                {
                    oldExpr.OnDetached(storage.Owner);
                }
            }

            storage.ThemeStyleValue = newValue;

            UpdateEffectiveValue(storage,
                                 newValue,
                                 BaseValueSourceInternal.ThemeStyle,
                                 false,                                     // coerceWithCurrentValue
                                 false,                                     // coerceValue
                                 newValue == DependencyProperty.UnsetValue, // clearValue
                                 true);                                     // propagateChanges
        }
        internal static void SetAnimationValue(INTERNAL_PropertyStorage storage,
                                               object value)
        {
            if (storage.IsExpression || storage.IsExpressionFromStyle)
            {
                BindingExpression currentExpr = storage.ModifiedValue.BaseValue as BindingExpression;
                if (currentExpr != null)
                {
                    currentExpr.OnDetached(storage.Owner);
                }
            }

            storage.AnimatedValue = value;

            UpdateEffectiveValue(storage,
                                 value,
                                 BaseValueSourceInternal.Animated,
                                 false,                                  // coerceWithCurrentValue
                                 false,                                  // coerceValue
                                 value == DependencyProperty.UnsetValue, // clearValue
                                 true);                                  // propagateChanges
        }
        /// <summary>
        /// Attemp to get a Property Storage for an inherited property
        /// (faster than generic accessor 'TryGetStorage')
        /// </summary>
        /// <param name="dependencyObject"></param>
        /// <param name="dependencyProperty"></param>
        /// <param name="createIfNotFoud">when set to true, it forces the creation of the storage if it does not exists yet.</param>
        /// <param name="storage"></param>
        /// <returns></returns>
        internal static bool TryGetInheritedPropertyStorage(DependencyObject dependencyObject,
                                                            DependencyProperty dependencyProperty,
                                                            bool createIfNotFoud,
                                                            out INTERNAL_PropertyStorage storage)
        {
            // Create the Storage if it does not already exist
            if (dependencyObject.INTERNAL_AllInheritedProperties.TryGetValue(dependencyProperty, out storage))
            {
                return(true);
            }

            if (createIfNotFoud)
            {
                // Get the type metadata (if any):
                PropertyMetadata typeMetadata = dependencyProperty.GetTypeMetaData(dependencyObject.GetType());

                global::System.Diagnostics.Debug.Assert(typeMetadata != null && typeMetadata.Inherits,
                                                        string.Format("{0} is not an inherited property.", dependencyProperty.Name));

                // Create the storage:
                storage = new INTERNAL_PropertyStorage(dependencyObject, dependencyProperty, typeMetadata);

                //-----------------------
                // CHECK IF THE PROPERTY BELONGS TO THE OBJECT (OR TO ONE OF ITS ANCESTORS):
                //-----------------------
                //below: we check if the property is useful to the current DependencyObject, in which case we set it as its inheritedValue in "PropertyStorageDictionary"
                if (dependencyProperty.OwnerType.IsAssignableFrom(dependencyObject.GetType()))
                {
                    //-----------------------
                    // ADD THE STORAGE TO "INTERNAL_PropertyStorageDictionary"
                    //-----------------------
                    dependencyObject.INTERNAL_PropertyStorageDictionary.Add(dependencyProperty, storage);
                }
                dependencyObject.INTERNAL_AllInheritedProperties.Add(dependencyProperty, storage);
            }

            return(createIfNotFoud);
        }
        internal static void ClearValueCommon(INTERNAL_PropertyStorage storage)
        {
            // Check for binding expression
            BindingExpression currentExpr = storage.IsExpression
                                            ? storage.LocalValue as BindingExpression
                                            : null;

            if (currentExpr != null)
            {
                currentExpr.OnDetached(storage.Owner);
            }

            // Reset local value
            storage.LocalValue = DependencyProperty.UnsetValue;

            UpdateEffectiveValue(storage,
                                 DependencyProperty.UnsetValue,
                                 BaseValueSourceInternal.Local,
                                 false, // coerceWithCurrentValue
                                 false, // coerceValue
                                 true,  // clearValue
                                 true); // propagateChanges
        }
示例#28
0
 private static void ComputeEffectiveValue(INTERNAL_PropertyStorage storage,
                                           out object effectiveValue,
                                           out BaseValueSourceInternal kind)
 {
     /*if ((effectiveValue = storage.VisualStateValue) != INTERNAL_NoValue.NoValue)
      * {
      *  kind = KindOfValue.VisualState;
      * }
      * else */
     if (!storage.IsAnimatedOverLocal &&
         (effectiveValue = storage.LocalValue) != DependencyProperty.UnsetValue)
     {
         kind = BaseValueSourceInternal.Local;
     }
     else if (storage.IsAnimatedOverLocal &&
              (effectiveValue = storage.AnimatedValue) != DependencyProperty.UnsetValue)
     {
         kind = BaseValueSourceInternal.Animated;
     }
     else if ((effectiveValue = storage.LocalStyleValue) != DependencyProperty.UnsetValue)
     {
         kind = BaseValueSourceInternal.LocalStyle;
     }
     else if ((effectiveValue = storage.ImplicitStyleValue) != DependencyProperty.UnsetValue)
     {
         kind = BaseValueSourceInternal.ImplicitStyle;
     }
     else if ((effectiveValue = storage.InheritedValue) != DependencyProperty.UnsetValue)
     {
         kind = BaseValueSourceInternal.Inherited;
     }
     else // Property default value
     {
         effectiveValue = storage.TypeMetadata.DefaultValue;
         kind           = BaseValueSourceInternal.Default;
     }
 }
        /// <summary>
        /// Attempt to get a Property Storage
        /// </summary>
        /// <param name="dependencyObject"></param>
        /// <param name="dependencyProperty"></param>
        /// <param name="createIfNotFoud">when set to true, it forces the creation of the storage if it does not exists yet.</param>
        /// <param name="storage"></param>
        /// <returns></returns>
        public static bool TryGetStorage(DependencyObject dependencyObject,
                                         DependencyProperty dependencyProperty,
                                         bool createIfNotFoud,
                                         out INTERNAL_PropertyStorage storage)
        {
            if (dependencyObject.INTERNAL_PropertyStorageDictionary.TryGetValue(dependencyProperty, out storage))
            {
                return(true);
            }

            if (createIfNotFoud)
            {
                // Get the type metadata
                PropertyMetadata typeMetadata = dependencyProperty.GetTypeMetaData(dependencyObject.GetType());

                //----------------------
                // CREATE A NEW STORAGE:
                //----------------------

                storage = new INTERNAL_PropertyStorage(dependencyObject, dependencyProperty, typeMetadata);
                dependencyObject.INTERNAL_PropertyStorageDictionary.Add(dependencyProperty, storage);

                //-----------------------
                // CHECK IF THE PROPERTY IS INHERITABLE:
                //-----------------------
                if (typeMetadata.Inherits)
                {
                    //-----------------------
                    // ADD THE STORAGE TO "INTERNAL_AllInheritedProperties" IF IT IS NOT ALREADY THERE:
                    //-----------------------
                    dependencyObject.INTERNAL_AllInheritedProperties.Add(dependencyProperty, storage);
                }
            }

            return(createIfNotFoud);
        }
        private static void UpdateEffectiveValue(INTERNAL_PropertyStorage storage,
                                                 object newValue,
                                                 BaseValueSourceInternal newValueSource,
                                                 bool coerceWithCurrentValue,
                                                 bool coerceValue,
                                                 bool clearValue,
                                                 bool propagateChanges)
        {
            global::System.Diagnostics.Debug.Assert((coerceWithCurrentValue == coerceValue && !coerceValue) || coerceValue != coerceWithCurrentValue);

            bool isCoerceOperation = coerceValue || coerceWithCurrentValue;
            BaseValueSourceInternal oldBaseValueSource = storage.BaseValueSourceInternal;

            object            oldValue;
            BindingExpression currentExpr = null;

            // Compute new value
            object effectiveValue;
            BaseValueSourceInternal effectiveValueKind;

            if (isCoerceOperation)
            {
                // Source and base value are unchanged during coercion operation
                effectiveValue     = newValue;
                effectiveValueKind = oldBaseValueSource;

                // Get old value before it gets overriden
                oldValue = GetEffectiveValue(storage);
            }
            else
            {
                ComputeEffectiveValue(storage, out effectiveValue, out effectiveValueKind);

                // Check for early exit if effective value is not impacted (if we are doing
                // a coerce operation, we have to go through the update process)
                if (effectiveValueKind == oldBaseValueSource &&
                    newValueSource < effectiveValueKind)
                {
                    // value source remains the same.
                    // Exit if the newly set value is of lower precedence than the effective value.
                    return;
                }

                // Get old value before it gets overriden
                oldValue = GetEffectiveValue(storage);

                currentExpr = (storage.IsExpression || storage.IsExpressionFromStyle) ? storage.ModifiedValue.BaseValue as BindingExpression : null;

#if USEASSERT
                // If the current base value is a BindingExpression, it should have been detached by now
                // Or is the same instance as 'effectiveValue' (this occurs when we update a property bound to a
                // BindingExpression)
                global::System.Diagnostics.Debug.Assert(currentExpr == null ||
                                                        !currentExpr.IsAttached ||
                                                        object.ReferenceEquals(currentExpr, effectiveValue), "Binding expression should be detached.");
#endif

                storage.ResetValue();

                // Update the base value source
                storage.BaseValueSourceInternal = effectiveValueKind;
            }

            object computedValue;

            if (!isCoerceOperation)
            {
                BindingExpression newExpr = effectiveValue as BindingExpression;
                if (newExpr == null)
                {
                    computedValue = storage.Property.PropertyType == typeof(string)
                                    ? effectiveValue?.ToString()
                                    : effectiveValue;
                    storage.Value = computedValue;
                }
                else
                {
#if USEASSERT
                    global::System.Diagnostics.Debug.Assert(effectiveValueKind == BaseValueSourceInternal.Local || effectiveValueKind == BaseValueSourceInternal.LocalStyle);
#endif

                    // If the new BindingExpression is the same as the current one,
                    // the BindingExpression is already attached
                    bool isNewBinding = !object.ReferenceEquals(currentExpr, newExpr);
                    if (isNewBinding)
                    {
                        if (newExpr.IsAttached)
                        {
                            throw new InvalidOperationException(string.Format("Cannot attach an instance of '{0}' multiple times", typeof(BindingExpression)));
                        }
                        newExpr.OnAttached(storage.Owner);
                        storage.Value = newExpr; // Set the new base value
                    }

                    if (effectiveValueKind == BaseValueSourceInternal.Local)
                    {
                        storage.SetExpressionValue(storage.TypeMetadata.DefaultValue, newExpr);
                    }
                    else
                    {
                        storage.SetExpressionFromStyleValue(storage.TypeMetadata.DefaultValue, newExpr);
                    }

                    // 1- 'isNewBinding == true' means that we are attaching a new BindingExpression.
                    // 2- 'newValue is BindingExpression == true' means that we are re-evaluating a BindingEpression
                    // (usually by calling RefreshBindingExpressionCommon)
                    // 3- Otherwise we are trying to change the value of a TwoWay binding.
                    // In that case we have to preserve the BindingExpression (this is not the case if the first two
                    // situations), hence the following line :
                    computedValue = isNewBinding || newValue is BindingExpression?newExpr.GetValue(storage.Property, storage.Owner.GetType())
                                        : newValue;

                    computedValue = storage.Property.PropertyType == typeof(string)
                                    ? computedValue?.ToString()
                                    : computedValue;
                    storage.ModifiedValue.ExpressionValue = computedValue;
                }
            }
            else
            {
                computedValue = coerceWithCurrentValue ? newValue : GetCoercionBaseValue(storage);
                if (coerceValue)
                {
                    storage.ResetCoercedValue();
                }
            }

            // Coerce to current value
            if (coerceWithCurrentValue)
            {
                object baseValue = GetCoercionBaseValue(storage);
                ProcessCoerceValue(storage,
                                   ref computedValue,
                                   oldValue,
                                   baseValue,
                                   true);
            }

            // Coerce Value
            // We don't want to coerce the value if it's being reset to the property's default value
            if (storage.TypeMetadata.CoerceValueCallback != null && !(clearValue && storage.FullValueSource == (FullValueSource)BaseValueSourceInternal.Default))
            {
                object baseValue = GetCoercionBaseValue(storage);
                ProcessCoerceValue(storage,
                                   ref computedValue,
                                   oldValue,
                                   baseValue,
                                   false);
            }

            // Reset old value inheritance context
            if (oldBaseValueSource == BaseValueSourceInternal.Local)
            {
                // Notes:
                // - Inheritance context is only handled by local value
                // - We use null instead of the actual DependencyProperty
                // as the parameter is ignored in the current implentation.
                storage.Owner.RemoveSelfAsInheritanceContext(oldValue, null /*storage.Property*/);
            }

            // Set new value inheritance context
            if (effectiveValueKind == BaseValueSourceInternal.Local)
            {
                // Check above
                storage.Owner.ProvideSelfAsInheritanceContext(computedValue, null /*storage.Property*/);
            }

            if (!ArePropertiesEqual(oldValue, computedValue, storage.Property.PropertyType))
            {
                // Raise the PropertyChanged event
                if (!storage.TypeMetadata.Inherits || ShouldRaisePropertyChanged(storage))
                {
                    OnPropertyChanged(storage, oldValue, computedValue);
                }

                // Propagate to children if property is inherited
                if (storage.TypeMetadata.Inherits && propagateChanges)
                {
                    CascadeInheritedPropertyToChildren(storage, computedValue);
                }
            }

            // Update the source of the Binding, in case the previous value of a property was a Binding and the Mode was "TwoWay":
            if (currentExpr != null && currentExpr.ParentBinding.Mode == BindingMode.TwoWay) //note: we know that oldBindingExpression.IsUpdating is false because oldBindingExpression is only set in that case (otherwise, it is null).
            {
                currentExpr.TryUpdateSourceObject(computedValue);
            }
        }