Esempio n. 1
0
        /// <summary>
        ///     Callback on visiting each node in the descendency
        ///     during an inheritable property change
        /// </summary>
        private static bool OnInheritablePropertyChanged(
            DependencyObject d,
            InheritablePropertyChangeInfo info,
            bool visitedViaVisualTree)
        {
            Debug.Assert(d != null, "Must have non-null current node");

            DependencyProperty dp = info.Property;
            bool inheritanceNode  = IsInheritanceNode(d, dp);

            if (inheritanceNode)
            {
                BaseValueSourceInternal  oldValueSource = BaseValueSourceInternal.Default;
                INTERNAL_PropertyStorage storage;
                if (INTERNAL_PropertyStore.TryGetInheritedPropertyStorage(d, dp, false, out storage))
                {
                    oldValueSource = storage.BaseValueSourceInternal;
                }

                // If the oldValueSource is of lower precedence than Inheritance
                // only then do we need to Invalidate the property
                if (BaseValueSourceInternal.Inherited >= oldValueSource)
                {
                    if (visitedViaVisualTree && typeof(FrameworkElement).IsInstanceOfType(d))
                    {
                        DependencyObject logicalParent = ((FrameworkElement)d).Parent;
                        if (logicalParent != null)
                        {
                            DependencyObject visualParent = VisualTreeHelper.GetParent(d);
                            if (visualParent != null && visualParent != logicalParent)
                            {
                                return(false);
                            }
                        }
                    }

                    return(d.SetInheritedValue(dp, info.NewValue, false));
                }
                else
                {
                    if (storage == null)
                    {
                        // get the storage if we didn't to it ealier.
                        INTERNAL_PropertyStore.TryGetInheritedPropertyStorage(d, dp, true, out storage);
                    }

                    // set the inherited value so that it is known if at some point,
                    // the value of higher precedence that is currently used is removed.
                    // we know that the value of the property is not changing, so we can
                    // skip the call to UpdateEffectiveValue(...)
                    storage.InheritedValue = info.NewValue;
                    return(false);
                }
            }

            return(false);
        }
Esempio n. 2
0
 internal void OnInheritedPropertyChanged(ref InheritablePropertyChangeInfo info)
 {
     if (IsFE)
     {
         _fe.RaiseInheritedPropertyChangedEvent(ref info);
     }
     else if (IsFCE)
     {
         _fce.RaiseInheritedPropertyChangedEvent(ref info);
     }
 }
 // Token: 0x060064AC RID: 25772 RVA: 0x001C3DC3 File Offset: 0x001C1FC3
 internal void OnInheritedPropertyChanged(ref InheritablePropertyChangeInfo info)
 {
     if (this.IsFE)
     {
         this._fe.RaiseInheritedPropertyChangedEvent(ref info);
         return;
     }
     if (this.IsFCE)
     {
         this._fce.RaiseInheritedPropertyChangedEvent(ref info);
     }
 }
Esempio n. 4
0
        private static bool 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;
            Expression 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(false);
                }

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

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

#if USEASSERT
                // If the current base value is an Expression, 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)
            {
                var newExpr = effectiveValue as Expression;
                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 Expression is the same as the current one,
                    // the Expression 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", newExpr.GetType()));
                        }
                        newExpr.OnAttach(storage.Owner, storage.Property);
                        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 Expression.
                    // 2- 'newValue is Expression == true' means that we are re-evaluating an Expression
                    // (usually by calling RefreshExpressionCommon)
                    // 3- Otherwise we are trying to change the value of a TwoWay binding.
                    // In that case we have to preserve the Expression (this is not the case if the first two
                    // situations), hence the following line :
                    computedValue = isNewBinding || newValue is Expression?newExpr.GetValue(storage.Owner, storage.Property)
                                        : 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*/);
            }

            bool valueChanged;
            if (valueChanged = (storage.INTERNAL_IsVisualValueDirty || !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)
                {
                    if (storage.Owner is FrameworkElement rootElement)
                    {
                        InheritablePropertyChangeInfo info = new InheritablePropertyChangeInfo(rootElement,
                                                                                               storage.Property,
                                                                                               oldValue, oldBaseValueSource,
                                                                                               computedValue, newValueSource);
                        TreeWalkHelper.InvalidateOnInheritablePropertyChange(rootElement, info);
                    }
                }
                storage.INTERNAL_IsVisualValueDirty = false;
            }

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

            // Raise the InvalidateMeasure or InvalidateArrange
            storage.Owner.OnPropertyChanged(new DependencyPropertyChangedEventArgs(oldValue, newValue, storage.Property));
            return(valueChanged);
        }
 internal InheritedPropertyChangedEventArgs(ref InheritablePropertyChangeInfo info)
 {
     _info = info;
 }
Esempio n. 6
0
        internal static void InvalidateOnInheritablePropertyChange(FrameworkElement fe, InheritablePropertyChangeInfo info)
        {
            if (fe.HasLogicalChildren || (fe.INTERNAL_VisualChildrenInformation != null &&
                                          fe.INTERNAL_VisualChildrenInformation.Count > 0))
            {
                DescendentsWalker <InheritablePropertyChangeInfo> walker = new DescendentsWalker <InheritablePropertyChangeInfo>(
                    TreeWalkPriority.LogicalTree, InheritablePropertyChangeDelegate, info);

                walker.StartWalk(fe, true);
            }

#if false
            if (rootFE != null)
            {
                if (rootFE.HasLogicalChildren)
                {
                    rootFE.IsLogicalChildrenIterationInProgress = true;
                    try
                    {
                        IEnumerator logicalChildren = rootFE.LogicalChildren;
                        if (logicalChildren != null)
                        {
                            while (logicalChildren.MoveNext())
                            {
                                DependencyObject child = logicalChildren.Current as DependencyObject;
                                if (child != null)
                                {
                                    child.SetInheritedValue(info.Property, info.NewValue, true);
                                }
                            }
                        }
                    }
                    finally
                    {
                        rootFE.IsLogicalChildrenIterationInProgress = false;
                    }
                }
            }

            if (rootUIE != null)
            {
                if (rootUIE.INTERNAL_VisualChildrenInformation != null)
                {
                    foreach (UIElement child in rootUIE.INTERNAL_VisualChildrenInformation.Keys)
                    {
                        child.SetInheritedValue(info.Property, info.NewValue, true);
                    }
                }
            }
#endif // false
        }
Esempio n. 7
0
        internal static void InvalidateOnInheritablePropertyChange(FrameworkElement fe, InheritablePropertyChangeInfo info)
        {
            if (HasChildren(fe))
            {
                DescendentsWalker <InheritablePropertyChangeInfo> walker = new DescendentsWalker <InheritablePropertyChangeInfo>(
                    TreeWalkPriority.LogicalTree, InheritablePropertyChangeDelegate, info);

                walker.StartWalk(fe, true);
            }
        }