internal void SetValue(object value, KindOfValue kindOfValue)
 {
     if (kindOfValue == KindOfValue.Local)
     {
         Local = value;
         if (value == INTERNAL_NoValue.NoValue)
         {
             ActiveValue = Animated == INTERNAL_NoValue.NoValue ? KindOfValue.Local : KindOfValue.Animated;
         }
         else
         {
             ActiveValue = KindOfValue.Local;
         }
     }
     else if (kindOfValue == KindOfValue.Animated)
     {
         Animated = value;
         if (value == INTERNAL_NoValue.NoValue)
         {
             ActiveValue = KindOfValue.Local;
         }
         else
         {
             ActiveValue = KindOfValue.Animated;
         }
     }
 }
예제 #2
0
        internal static void SetSpecificValue(INTERNAL_PropertyStorage storage, KindOfValue kindOfValueToSet, object newValue)
        {
            var  typeMetadata       = storage.TypeMetadata;
            bool inherits           = typeMetadata != null && typeMetadata.Inherits;
            bool impactsActualValue = DoesSpecificValueImpactActualValue(storage, kindOfValueToSet);
            bool coerces            = typeMetadata != null && typeMetadata.CoerceValueCallback != null;

            //-----------------------
            // DETERMINE IF WE SHOULD RAISE THE "PROPERTYCHANGED" EVENT AND CASCADE THE PROPERTY TO THE CHILDREN:
            //-----------------------

            bool raisePropertyChanged =
                impactsActualValue &&
                (!inherits || storage.Property.OwnerType.IsAssignableFrom(storage.Owner.GetType()) || storage.Property == FrameworkElement.DataContextProperty);    // If the property is inherited, we should only raise the PropertyChanged event on the types that the property is compatible with (unless it's the DataContext property, in which case we always raise the PropertyChanged event).
            //todo: are attached properties properly handled?

            bool cascadetoChildren =
                impactsActualValue &&
                inherits;

            //we make sure that we don't raise PropertyChanged for IsEnabled if its inherited value is false, because a "false" inherited value has priority over any local value.
            if (storage._isIsEnabledOrIsHitTestVisibleProperty)
            {
                object value;
                if ((value = storage.InheritedValue) != INTERNAL_NoValue.NoValue && value != null && (((bool)value) == false))
                {
                    raisePropertyChanged = false; //we don't want to call RaisePropertyChanged... because the inherited value overrides the local value if it is false.
                    cascadetoChildren    = false;
                }
            }

            //-----------------------
            // GET THE OLD VALUE IF NECESSARY:
            //-----------------------

            object oldValue;

            if (raisePropertyChanged)
            {
                oldValue = GetValue(storage, typeMetadata);
            }
            else
            {
                oldValue = null;
            }

            //-----------------------
            // SET THE VALUE IN THE STORAGE:
            //-----------------------

            switch (kindOfValueToSet)
            {
            case KindOfValue.Coerced:
                storage.CoercedValue = newValue;
                break;

            case KindOfValue.VisualState:
                //oldValue = (storage.VisualStateValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.VisualStateValue);
                storage.VisualStateValue = newValue;
                break;

            case KindOfValue.Local:
                //oldValue = (storage.Local == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.Local);
                storage.Local = newValue;
                break;

            case KindOfValue.Animated:
                //oldValue = (storage.AnimationValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.AnimationValue);
                storage.AnimationValue = newValue;
                break;

            case KindOfValue.LocalStyle:
                //oldValue = (storage.LocalStyleValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.LocalStyleValue);
                storage.LocalStyleValue = newValue;
                break;

            case KindOfValue.ImplicitStyle:
                //oldValue = (storage.ImplicitStyleValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.ImplicitStyleValue);
                storage.ImplicitStyleValue = newValue;
                break;

            case KindOfValue.Inherited:
                //inherited is a special case
                break;

            default:
                break;
            }

            // Update the "ActualValue" and the "CoercedValue":
            if (impactsActualValue)
            {
                // If we are removing the value by setting it to "NoValue", we need to recompute the ActualValue:
                if (newValue == INTERNAL_NoValue.NoValue) //we need to update the ActualValue because the new value is going to be the one with the highest priority.
                {
                    newValue = ComputeActualValue(storage, typeMetadata, true);
                }

                //if the new Value changes the actual value and is coerced, we compute the coerced value and set it.
                if (coerces && kindOfValueToSet != KindOfValue.Coerced)
                {
                    // Compute the coerced value:
                    newValue = typeMetadata.CoerceValueCallback(storage.Owner, newValue);

                    // Remember the coerced value:
                    storage.CoercedValue = newValue;
                    storage.ActualValue  = newValue;
                }
                else
                {
                    storage.ActualValue = newValue;
                }
            }

            //-----------------------
            // RAISE THE "PROPERTYCHANGED" EVENT:
            //-----------------------

            if (raisePropertyChanged && ShouldRaisePropertyChanged(storage))
            {
                OnPropertyChanged(storage, oldValue, newValue);
            }

            //-----------------------
            // PROPAGATE TO CHILDREN (INHERITED PROPERTIES ONLY):
            //-----------------------

            if (cascadetoChildren)
            {
                CascadeInheritedPropertyToChildren(storage, newValue);

                HandleSpecialPropertiesThatShouldInheritDataContext(storage, newValue);
            }
        }
예제 #3
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) || storage.ActiveLocalValue.ActiveValue != KindOfValue.Local) &&
                (kind <= KindOfValue.Animated || ((value = storage.AnimationValue) == INTERNAL_NoValue.NoValue) || storage.ActiveLocalValue.ActiveValue != KindOfValue.Animated) &&
                (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);
        }
        static void SetSpecificValue(INTERNAL_PropertyStorage storage, KindOfValue kindOfValueToSet, object newValue, PropertyMetadata typeMetadata)
        {
#if PERFSTAT
            var t = Performance.now();
#endif
            if (typeMetadata == null)
            {
                typeMetadata = storage.Property.GetTypeMetaData(storage.Owner.GetType());
            }
            object oldValue = GetValue(storage, typeMetadata);
            bool   raisePropertyChangedAndCascadetoChildren = true;

            bool impactsActualValue = DoesSpecificValueImpactActualValue(storage, kindOfValueToSet);
            bool coerces            = typeMetadata != null && typeMetadata.CoerceValueCallback != null;

            switch (kindOfValueToSet)
            {
            case KindOfValue.Coerced:
                storage.CoercedValue = newValue;
                break;

            case KindOfValue.VisualState:
                //oldValue = (storage.VisualStateValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.VisualStateValue);
                storage.VisualStateValue = newValue;
                break;

            case KindOfValue.Local:
                //oldValue = (storage.Local == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.Local);
                storage.Local = newValue;
                break;

            case KindOfValue.Animated:
                //oldValue = (storage.AnimationValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.AnimationValue);
                storage.AnimationValue = newValue;
                break;

            case KindOfValue.LocalStyle:
                //oldValue = (storage.LocalStyleValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.LocalStyleValue);
                storage.LocalStyleValue = newValue;
                break;

            case KindOfValue.ImplicitStyle:
                //oldValue = (storage.ImplicitStyleValue == INTERNAL_NoValue.NoValue ? (typeMetadata != null ? typeMetadata.DefaultValue : null) : storage.ImplicitStyleValue);
                storage.ImplicitStyleValue = newValue;
                break;

            case KindOfValue.Inherited:
                //inherited is a special case
                break;

            default:
                break;
            }

            if (newValue == INTERNAL_NoValue.NoValue) //we consider that the new value is the one with the highest priority since we removed the former one.
            {
                newValue = GetValueWithoutCoerce(storage, typeMetadata);
            }

            //if the new Value changes the actual value and is coerced, we compute the coerced value and set it.
            if (coerces && impactsActualValue && kindOfValueToSet != KindOfValue.Coerced)
            {
                // Compute the coerced value:
                newValue = typeMetadata.CoerceValueCallback(storage.Owner, newValue);

                // A coerced value has the highest priority so it does impact the actual value:
                impactsActualValue = true;

                // Remember the coerced value:
                storage.CoercedValue = newValue;
            }

            //we make sure that we don't raise PropertyChanged for IsEnabled if its inherited value is false, because a "false" inherited value has priority over any local value.
            if (storage._isIsEnabledOrIsHitTestVisibleProperty)
            {
                object value;
                if ((value = storage.InheritedValue) != INTERNAL_NoValue.NoValue && value != null && (((bool)value) == false))
                {
                    raisePropertyChangedAndCascadetoChildren = false; //we don't want to call RaisePropertyChanged... because the inherited value overrides the local value if it is false.
                }
            }

            if (raisePropertyChangedAndCascadetoChildren && impactsActualValue)
            {
#if PERFSTAT
                Performance.Counter("INTERNAL_PropertyStore.SetSpecificValue", t);
#endif
                RaisePropertyChangedAndCascadeToChildren(storage, oldValue, newValue, typeMetadata); //Note: in the case of a value that has no CoerceCallBack, this is equal to newValue.
            }
        }