Пример #1
0
        /// <summary>
        ///     Read the value of this field on a DependencyObject instance.
        /// </summary>
        /// <param name="instance">The DependencyObject from which to get the value.</param>
        /// <returns></returns>
        public T GetValue(DependencyObject instance)
        {
            if (instance != null)
            {
                if (_hasBeenSet)
                {
                    EntryIndex entryIndex = instance.LookupEntry(_globalIndex);

                    if (entryIndex.Found)
                    {
                        object value = instance.EffectiveValues[entryIndex.Index].LocalValue;

                        if (value != DependencyProperty.UnsetValue)
                        {
                            return((T)value);
                        }
                    }
                    return(_defaultValue);
                }
                else
                {
                    return(_defaultValue);
                }
            }
            else
            {
                throw new ArgumentNullException("instance");
            }
        }
Пример #2
0
        /// <summary>
        ///     Clear this field from the given DependencyObject instance.
        /// </summary>
        /// <param name="instance"></param>
        public void ClearValue(DependencyObject instance)
        {
            if (instance != null)
            {
                EntryIndex entryIndex = instance.LookupEntry(_globalIndex);

                instance.UnsetEffectiveValue(entryIndex, null /* dp */, null /* metadata */);
            }
            else
            {
                throw new ArgumentNullException("instance");
            }
        }
Пример #3
0
        /// <summary>
        ///     Write the given value onto a DependencyObject instance.
        /// </summary>
        /// <param name="instance">The DependencyObject on which to set the value.</param>
        /// <param name="value">The value to set.</param>
        public void SetValue(DependencyObject instance, T value)
        {
            if (instance != null)
            {
                EntryIndex entryIndex = instance.LookupEntry(_globalIndex);

                // Set the value if it's not the default, otherwise remove the value.
                if (!object.ReferenceEquals(value, _defaultValue))
                {
                    instance.SetEffectiveValue(entryIndex, null /* dp */, _globalIndex, null /* metadata */, value, BaseValueSourceInternal.Local);
                    _hasBeenSet = true;
                }
                else
                {
                    instance.UnsetEffectiveValue(entryIndex, null /* dp */, null /* metadata */);
                }
            }
            else
            {
                throw new ArgumentNullException("instance");
            }
        }
Пример #4
0
        /// <summary> 
        /// Used to determine whether a DependencyObject has a value with an expression, such as a resource reference.
        /// </summary> 
        /// <returns> 
        /// True if Dependency object has a value with an expression
        /// </returns> 
        internal bool HasAnyExpression()
        {
            EffectiveValueEntry[] effectiveValues = EffectiveValues;
            uint numEffectiveValues = EffectiveValuesCount; 
            bool result = false;
 
            for (uint i = 0; i < numEffectiveValues; i++) 
            {
                DependencyProperty dp = 
                    DependencyProperty.RegisteredPropertyList.List[effectiveValues[i].PropertyIndex];

                if (dp != null)
                { 
                    EntryIndex entryIndex = new EntryIndex(i);
                    // The expression check only needs to be done when isChecking is true 
                    // because if we return false here the Freeze() call will fail. 
                    if (HasExpression(entryIndex, dp))
                    { 
                        result = true;
                        break;
                    }
                } 
            }
 
            return result; 
        }
Пример #5
0
        /// <summary> 
        ///     Retrieve the local value of a property (if set)
        /// </summary>
        /// <returns>
        ///     The local value. DependencyProperty.UnsetValue if no local value was 
        ///     set via <cref see="SetValue"/>.
        /// </returns> 
        internal object ReadLocalValueEntry(EntryIndex entryIndex, DependencyProperty dp, bool allowDeferredReferences) 
        {
            if (!entryIndex.Found) 
            {
                return DependencyProperty.UnsetValue;
            }
 
            EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
            object value = entry.IsCoercedWithCurrentValue ? entry.ModifiedValue.CoercedValue : entry.LocalValue; 
 
            // convert a deferred reference into a real value
            if (!allowDeferredReferences && entry.IsDeferredReference) 
            {
                // localValue may still not be a DeferredReference, e.g.
                // if it is an expression whose value is a DeferredReference.
                // So a little more work is needed before converting the value. 
                DeferredReference dr = value as DeferredReference;
                if (dr != null) 
                { 
                    value = dr.GetValue(entry.BaseValueSourceInternal);
                } 
            }

            // treat Expression marker as "unset"
            if (value == ExpressionInAlternativeStore) 
            {
                value = DependencyProperty.UnsetValue; 
            } 

            return value; 
        }
Пример #6
0
        [FriendAccessAllowed] // Built into Base, also used by Core.
        internal EffectiveValueEntry GetValueEntry( 
            EntryIndex          entryIndex,
            DependencyProperty  dp,
            PropertyMetadata    metadata,
            RequestFlags        requests) 
        {
            EffectiveValueEntry entry; 
 
            if (dp.ReadOnly)
            { 
                if (metadata == null)
                {
                    metadata = dp.GetMetadata(DependencyObjectType);
                } 

                GetReadOnlyValueCallback getValueCallback = metadata.GetReadOnlyValueCallback; 
                if (getValueCallback != null) 
                {
                    BaseValueSourceInternal valueSource; 
                    entry = new EffectiveValueEntry(dp);
                    entry.Value = getValueCallback(this, out valueSource);
                    entry.BaseValueSourceInternal = valueSource;
                    return entry; 
                }
            } 
 
            if (entryIndex.Found)
            { 
                if ((requests & RequestFlags.RawEntry) != 0)
                {
                    entry = _effectiveValues[entryIndex.Index];
                } 
                else
                { 
                    entry = GetEffectiveValue( 
                                entryIndex,
                                dp, 
                                requests);
                }
            }
            else 
            {
                entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Unknown); 
            } 

            if (entry.Value == DependencyProperty.UnsetValue) 
            {
                if (dp.IsPotentiallyInherited)
                {
                    if (metadata == null) 
                    {
                        metadata = dp.GetMetadata(DependencyObjectType); 
                    } 

                    if (metadata.IsInherited) 
                    {
                        DependencyObject inheritanceParent = InheritanceParent;
                        if (inheritanceParent != null)
                        { 
                            entryIndex = inheritanceParent.LookupEntry(dp.GlobalIndex);
 
                            if (entryIndex.Found) 
                            {
                                entry = inheritanceParent.GetEffectiveValue( 
                                                entryIndex,
                                                dp,
                                                requests & RequestFlags.DeferredReferences);
                                entry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; 
                            }
                        } 
                    } 

                    if (entry.Value != DependencyProperty.UnsetValue) 
                    {
                        return entry;
                    }
                } 

                if ((requests & RequestFlags.SkipDefault) == 0) 
                { 
                    if (dp.IsPotentiallyUsingDefaultValueFactory)
                    { 
                        if (metadata == null)
                        {
                            metadata = dp.GetMetadata(DependencyObjectType);
                        } 

                        if (((requests & (RequestFlags.DeferredReferences | RequestFlags.RawEntry)) != 0) && metadata.UsingDefaultValueFactory) 
                        { 
                            entry.BaseValueSourceInternal = BaseValueSourceInternal.Default;
 
                            entry.Value = new DeferredMutableDefaultReference(metadata, this, dp);
                            return entry;
                        }
                    } 
                    else if (!dp.IsDefaultValueChanged)
                    { 
                        return EffectiveValueEntry.CreateDefaultValueEntry(dp, dp.DefaultMetadata.DefaultValue); 
                    }
 
                    if (metadata == null)
                    {
                        metadata = dp.GetMetadata(DependencyObjectType);
                    } 

                    return EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); 
                } 
            }
            return entry; 
        }
Пример #7
0
        /// <summary>
        /// If you derive from Freezable you will need to override this if your subclass
        /// has data that is not exposed via DPs.
        ///
        /// The default implementation goes through all DPs and returns false
        /// if any DP has an expression or if any Freezable DP cannot freeze.
        ///
        /// If you do override this method, you MUST call the base implementation.
        ///
        /// This is called by Freeze().
        /// </summary>
        /// <param name="isChecking">If this is true, the method will just check
        /// to see that the object can be frozen, but won't actually freeze it.
        /// </param>
        /// <returns>True if the Freezable is or can be frozen.</returns>
        protected virtual bool FreezeCore(bool isChecking)
        {
            EffectiveValueEntry[] effectiveValues = EffectiveValues;
            uint numEffectiveValues = EffectiveValuesCount;

            // Loop through all DPs and call their FreezeValueCallback.
            for (uint i = 0; i < numEffectiveValues; i++)
            {
                DependencyProperty dp =
                    DependencyProperty.RegisteredPropertyList.List[effectiveValues[i].PropertyIndex];

                if (dp != null)
                {
                    EntryIndex entryIndex = new EntryIndex(i);
                    PropertyMetadata metadata = dp.GetMetadata(DependencyObjectType);
                    
                    FreezeValueCallback freezeValueCallback = metadata.FreezeValueCallback;
                    if(!freezeValueCallback(this, dp, entryIndex, metadata, isChecking))
                    {
                        return false;
                    }
                }
            }

            return true;
        }
Пример #8
0
        //
        //  This method
        //  1. Sets the expression on a ModifiedValue entry 
        //
        private void SetExpressionValue(EntryIndex entryIndex, object value, object baseValue) 
        { 
            Debug.Assert(value != DependencyProperty.UnsetValue, "Value to be set cannot be UnsetValue");
            Debug.Assert(baseValue != DependencyProperty.UnsetValue, "BaseValue to be set cannot be UnsetValue"); 
            Debug.Assert(entryIndex.Found == true, "The baseValue for the expression should have been inserted prior to this and hence there should already been an entry for it.");

            // For thread-safety, sealed DOs can't modify _effectiveValues.
            Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified"); 

            EffectiveValueEntry entry = _effectiveValues[entryIndex.Index]; 
 
            entry.SetExpressionValue(value, baseValue);
            entry.ResetAnimatedValue(); 
            entry.ResetCoercedValue();
            _effectiveValues[entryIndex.Index] = entry;
        }
Пример #9
0
        [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
        internal void SetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, int targetIndex, PropertyMetadata metadata, object value, BaseValueSourceInternal valueSource) 
        { 
            Debug.Assert(value != DependencyProperty.UnsetValue, "Value to be set cannot be UnsetValue");
            Debug.Assert(valueSource != BaseValueSourceInternal.Unknown, "ValueSource cannot be Unknown"); 

            // For thread-safety, sealed DOs can't modify _effectiveValues.
            Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
 
            if (metadata != null &&
                metadata.IsInherited && 
                valueSource != BaseValueSourceInternal.Inherited && 
                !IsSelfInheritanceParent)
            { 
                SetIsSelfInheritanceParent();
                entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
            }
 
            EffectiveValueEntry entry;
            if (entryIndex.Found) 
            { 
                entry = _effectiveValues[entryIndex.Index];
            } 
            else
            {
                entry = new EffectiveValueEntry();
                entry.PropertyIndex = targetIndex; 
                InsertEntry(entry, entryIndex.Index);
                if (metadata != null && metadata.IsInherited) 
                { 
                    InheritableEffectiveValuesCount++;
                } 
            }

            bool hasExpressionMarker = (value == ExpressionInAlternativeStore);
 
            if (!hasExpressionMarker &&
                entry.HasExpressionMarker && 
                (valueSource == BaseValueSourceInternal.ThemeStyle || 
                 valueSource == BaseValueSourceInternal.ThemeStyleTrigger ||
                 valueSource == BaseValueSourceInternal.Style || 
                 valueSource == BaseValueSourceInternal.TemplateTrigger ||
                 valueSource == BaseValueSourceInternal.StyleTrigger ||
                 valueSource == BaseValueSourceInternal.ParentTemplate ||
                 valueSource == BaseValueSourceInternal.ParentTemplateTrigger)) 
            {
                entry.BaseValueSourceInternal = valueSource; 
                entry.SetExpressionValue(value, ExpressionInAlternativeStore); 
                entry.ResetAnimatedValue();
                entry.ResetCoercedValue(); 
            }
            else if (entry.IsExpression && entry.ModifiedValue.ExpressionValue == Expression.NoValue)
            {
                // we now have a value for an expression that is "hiding" - save it 
                // as the expression value
                entry.SetExpressionValue(value, entry.ModifiedValue.BaseValue); 
            } 
            else
            { 
                Debug.Assert(entry.BaseValueSourceInternal != BaseValueSourceInternal.Local || valueSource == BaseValueSourceInternal.Local,
                    "No one but another local value can stomp over an existing local value. The only way is to clear the entry");

                entry.BaseValueSourceInternal = valueSource; 
                entry.ResetValue(value, hasExpressionMarker);
            } 
 
            Debug.Assert(dp == null || (dp.GlobalIndex == entry.PropertyIndex), "EffectiveValueEntry & DependencyProperty do not match");
            _effectiveValues[entryIndex.Index] = entry; 
        }
Пример #10
0
        //
        //  This method 
        //  1. Is used to check if the given entryIndex needs any change. It
        //  could happen that we have made a call out and thereby caused changes 
        //  to the _effectiveValues store on the current element. In that case 
        //  we would need to aquire new value for the index.
        // 
        private EntryIndex CheckEntryIndex(EntryIndex entryIndex, int targetIndex)
        {
            uint effectiveValuesCount = EffectiveValuesCount;
            if (effectiveValuesCount > 0 && _effectiveValues.Length > entryIndex.Index) 
            {
                EffectiveValueEntry entry = _effectiveValues[entryIndex.Index]; 
                if (entry.PropertyIndex == targetIndex) 
                {
                    return new EntryIndex(entryIndex.Index); 
                }
            }

            return LookupEntry(targetIndex); 
        }
Пример #11
0
        // Token: 0x06000C6D RID: 3181 RVA: 0x0002EB78 File Offset: 0x0002CD78
        private static bool OnInheritablePropertyChanged(DependencyObject d, InheritablePropertyChangeInfo info, bool visitedViaVisualTree)
        {
            DependencyProperty  property = info.Property;
            EffectiveValueEntry oldEntry = info.OldEntry;
            EffectiveValueEntry newEntry = info.NewEntry;
            InheritanceBehavior inheritanceBehavior;
            bool flag  = TreeWalkHelper.IsInheritanceNode(d, property, out inheritanceBehavior);
            bool flag2 = TreeWalkHelper.IsForceInheritedProperty(property);

            if (!flag || (TreeWalkHelper.SkipNext(inheritanceBehavior) && !flag2))
            {
                return(inheritanceBehavior == InheritanceBehavior.Default || flag2);
            }
            PropertyMetadata metadata   = property.GetMetadata(d);
            EntryIndex       entryIndex = d.LookupEntry(property.GlobalIndex);

            if (!d.IsSelfInheritanceParent)
            {
                DependencyObject    frameworkParent      = FrameworkElement.GetFrameworkParent(d);
                InheritanceBehavior inheritanceBehavior2 = InheritanceBehavior.Default;
                if (frameworkParent != null)
                {
                    FrameworkObject frameworkObject = new FrameworkObject(frameworkParent, true);
                    inheritanceBehavior2 = frameworkObject.InheritanceBehavior;
                }
                if (!TreeWalkHelper.SkipNext(inheritanceBehavior) && !TreeWalkHelper.SkipNow(inheritanceBehavior2))
                {
                    d.SynchronizeInheritanceParent(frameworkParent);
                }
                if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown)
                {
                    oldEntry = EffectiveValueEntry.CreateDefaultValueEntry(property, metadata.GetDefaultValue(d, property));
                }
            }
            else
            {
                oldEntry = d.GetValueEntry(entryIndex, property, metadata, RequestFlags.RawEntry);
            }
            if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal)
            {
                if (visitedViaVisualTree && FrameworkElement.DType.IsInstanceOfType(d))
                {
                    DependencyObject parent = LogicalTreeHelper.GetParent(d);
                    if (parent != null)
                    {
                        DependencyObject parent2 = VisualTreeHelper.GetParent(d);
                        if (parent2 != null && parent2 != parent)
                        {
                            return(false);
                        }
                    }
                }
                return((d.UpdateEffectiveValue(entryIndex, property, metadata, oldEntry, ref newEntry, false, false, OperationType.Inherit) & (UpdateResult)5) == UpdateResult.ValueChanged);
            }
            if (flag2)
            {
                newEntry = new EffectiveValueEntry(property, FullValueSource.IsCoerced);
                return((d.UpdateEffectiveValue(d.LookupEntry(property.GlobalIndex), property, metadata, oldEntry, ref newEntry, false, false, OperationType.Inherit) & (UpdateResult)5) == UpdateResult.ValueChanged);
            }
            return(false);
        }
Пример #12
0
        private static bool DefaultFreezeValueCallback( 
            DependencyObject d,
            DependencyProperty dp, 
            EntryIndex entryIndex, 
            PropertyMetadata metadata,
            bool isChecking) 
        {
            // The expression check only needs to be done when isChecking is true
            // because if we return false here the Freeze() call will fail.
            if (isChecking) 
            {
                if (d.HasExpression(entryIndex, dp)) 
                { 
                    if (TraceFreezable.IsEnabled)
                    { 
                        TraceFreezable.Trace(
                            TraceEventType.Warning,
                            TraceFreezable.UnableToFreezeExpression,
                            d, 
                            dp,
                            dp.OwnerType); 
                    } 

                    return false; 
                }
            }

            if (!dp.IsValueType) 
            {
                object value = 
                    d.GetValueEntry( 
                        entryIndex,
                        dp, 
                        metadata,
                        RequestFlags.FullyResolved).Value;

                if (value != null) 
                {
                    Freezable valueAsFreezable = value as Freezable; 
 
                    if (valueAsFreezable != null)
                    { 
                        if (!valueAsFreezable.Freeze(isChecking))
                        {
                            if (TraceFreezable.IsEnabled)
                            { 
                                TraceFreezable.Trace(
                                    TraceEventType.Warning, 
                                    TraceFreezable.UnableToFreezeFreezableSubProperty, 
                                    d,
                                    dp, 
                                    dp.OwnerType);
                            }

                            return false; 
                        }
                    } 
                    else  // not a Freezable 
                    {
                        DispatcherObject valueAsDispatcherObject = value as DispatcherObject; 

                        if (valueAsDispatcherObject != null)
                        {
                            if (valueAsDispatcherObject.Dispatcher == null) 
                            {
                                // The property is a free-threaded DispatcherObject; since it's 
                                // already free-threaded it doesn't prevent this Freezable from 
                                // becoming free-threaded too.
                                // It is up to the creator of this type to ensure that the 
                                // DispatcherObject is actually immutable
                            }
                            else
                            { 
                                // The value of this property derives from DispatcherObject and
                                // has thread affinity; return false. 
 
                                if (TraceFreezable.IsEnabled)
                                { 
                                    TraceFreezable.Trace(
                                        TraceEventType.Warning,
                                        TraceFreezable.UnableToFreezeDispatcherObjectWithThreadAffinity,
                                        d, 
                                        dp,
                                        dp.OwnerType, 
                                        valueAsDispatcherObject ); 
                                }
 
                                return false;
                            }
                        }
 
                        // The property isn't a DispatcherObject.  It may be immutable (such as a string)
                        // or the user may have made it thread-safe.  It's up to the creator of the type to 
                        // do the right thing; we return true as an extensibility point. 
                    }
                } 
            }

            return true;
        } 
Пример #13
0
        // Makes a deep clone of a Freezable.  Helper method for
        // CloneCore(), CloneCurrentValueCore() and GetAsFrozenCore()
        //
        // If useCurrentValue is true it calls GetValue on each of the sourceFreezable's DPs; if false
        // it uses ReadLocalValue.
        private void CloneCoreCommon(Freezable sourceFreezable, bool useCurrentValue, bool cloneFrozenValues)
        {
            EffectiveValueEntry[] srcEffectiveValues = sourceFreezable.EffectiveValues;
            uint srcEffectiveValueCount = sourceFreezable.EffectiveValuesCount;

            // Iterate through the effective values array.  Note that default values aren't
            // stored here so the only defaults we'll come across are modified defaults,
            // which useCurrentValue = true uses and useCurrentValue = false ignores.
            for (uint i = 0; i < srcEffectiveValueCount; i++)
            {
                EffectiveValueEntry srcEntry = srcEffectiveValues[i];

                DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[srcEntry.PropertyIndex];

                // We need to skip ReadOnly properties otherwise SetValue will fail
                if ((dp != null) && !dp.ReadOnly)
                {
                    object sourceValue;

                    EntryIndex entryIndex = new EntryIndex(i);

                    if (useCurrentValue)
                    {
                        // Default values aren't in the EffectiveValues array
                        // so we won't see them as we iterate.  We do copy modified defaults.
                        Debug.Assert(srcEntry.BaseValueSourceInternal != BaseValueSourceInternal.Default || srcEntry.HasModifiers);

                        sourceValue = sourceFreezable.GetValueEntry(
                                            entryIndex,
                                            dp,
                                            null,
                                            RequestFlags.FullyResolved).Value;

                        // GetValue should not have returned UnsetValue
                        Debug.Assert(sourceValue != DependencyProperty.UnsetValue);
                    }
                    else // use base values
                    {
                        // If the local value has modifiers, ReadLocalValue will return the base
                        // value, which is what we want.  A modified default will return UnsetValue,
                        // which will be ignored at the call to SetValue
                        sourceValue = sourceFreezable.ReadLocalValueEntry(entryIndex, dp, true /* allowDeferredReferences */);

                        // For the useCurrentValue = false case we ignore any UnsetValues.
                        if (sourceValue == DependencyProperty.UnsetValue)
                        {
                            continue;
                        }

                        // If the DP is an expression ReadLocalValue will return the actual expression.
                        // In this case we need to copy it.
                        if (srcEntry.IsExpression)
                        {
                            sourceValue = ((Expression)sourceValue).Copy(this, dp);
                        }
                    }

                    //
                    // If the value of the current DP is a Freezable
                    // we need to recurse and call the appropriate Clone method in
                    // order to do a deep copy.
                    //

                    Debug.Assert(!(sourceValue is Expression && sourceValue is Freezable),
                        "This logic assumes Expressions and Freezables don't co-derive");

                    Freezable valueAsFreezable = sourceValue as Freezable;

                    if (valueAsFreezable != null)
                    {
                        Freezable valueAsFreezableClone;

                        //
                        // Choose between the four possible ways of
                        // cloning a Freezable
                        //
                        if (cloneFrozenValues) //CloneCore and CloneCurrentValueCore
                        {
                            valueAsFreezableClone = valueAsFreezable.CreateInstanceCore();

                            if (useCurrentValue)
                            {
                                // CloneCurrentValueCore implementation.  We clone even if the
                                // Freezable is frozen by recursing into CloneCurrentValueCore.
                                valueAsFreezableClone.CloneCurrentValueCore(valueAsFreezable);
                            }
                            else
                            {
                                // CloneCore implementation.  We clone even if the Freezable is
                                // frozen by recursing into CloneCore.
                                valueAsFreezableClone.CloneCore(valueAsFreezable);
                            }

                            sourceValue = valueAsFreezableClone;
                            Debug_VerifyCloneCommon(valueAsFreezable, valueAsFreezableClone, /*isDeepClone=*/ true);
                        }
                        else // skip cloning frozen values
                        {

                            if (!valueAsFreezable.IsFrozen)
                            {
                                valueAsFreezableClone = valueAsFreezable.CreateInstanceCore();

                                if (useCurrentValue)
                                {
                                    // GetCurrentValueAsFrozenCore implementation.  Only clone if the
                                    // Freezable is mutable by recursing into GetCurrentValueAsFrozenCore.
                                    valueAsFreezableClone.GetCurrentValueAsFrozenCore(valueAsFreezable);
                                }
                                else
                                {
                                    // GetAsFrozenCore implementation.  Only clone if the Freezable is
                                    // mutable by recursing into GetAsFrozenCore.
                                    valueAsFreezableClone.GetAsFrozenCore(valueAsFreezable);
                                }

                                sourceValue = valueAsFreezableClone;
                                Debug_VerifyCloneCommon(valueAsFreezable, valueAsFreezableClone, /*isDeepClone=*/ false);
                            }
                        }
                    }

                    SetValue(dp, sourceValue);
                }
            }
        }
Пример #14
0
        [FriendAccessAllowed] // Built into Base, also used by Core and Framework. 
        internal bool HasExpression(EntryIndex entryIndex, DependencyProperty dp)
        { 
            if (!entryIndex.Found) 
            {
                return false; 
            }

            EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
 
            object o = entry.LocalValue;
 
            bool result = (entry.HasExpressionMarker || o is Expression); 
            return result;
        } 
Пример #15
0
        [FriendAccessAllowed] // Declared in Base also used in Framework 
        internal UpdateResult UpdateEffectiveValue(
                EntryIndex          entryIndex,
                DependencyProperty  dp,
                PropertyMetadata    metadata, 
                EffectiveValueEntry oldEntry,
            ref EffectiveValueEntry newEntry, 
                bool                coerceWithDeferredReference, 
                bool                coerceWithCurrentValue,
                OperationType       operationType) 
        {
            if (dp == null)
            {
                throw new ArgumentNullException("dp"); 
            }
 
#region EventTracing 
#if VERBOSE_PROPERTY_EVENT
            bool isDynamicTracing = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); // This was under "normal" 
            if (isDynamicTracing)
            {
                ++InvalidationCount;
                if( InvalidationCount % 100 == 0 ) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, 
                                                         MS.Utility.EventType.Info, 
                                                         InvalidationCount );
                } 

                string TypeAndName = String.Format(CultureInfo.InvariantCulture, "[{0}]{1}({2})",GetType().Name,dp.Name,base.GetHashCode()); // FxCop wanted the CultureInfo.InvariantCulture

                EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, 
                                                     MS.Utility.EventType.StartEvent,
                                                     base.GetHashCode(), TypeAndName); // base.GetHashCode() to avoid calling a virtual, which FxCop doesn't like. 
            } 
#endif
 

#endregion EventTracing

#if NESTED_OPERATIONS_CHECK 
            // Are we invalidating out of control?
            if( NestedOperations > NestedOperationMaximum ) 
            { 
                // We're invalidating out of control, time to abort.
                throw new InvalidOperationException("Too many levels of nested DependencyProperty invalidations.  This usually indicates a circular reference in the application and the cycle needs to be broken."); 
            }
            NestedOperations++; // Decrement in the finally block
#endif
            int targetIndex = dp.GlobalIndex; 

            if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) 
            { 
                // Do a full get value of the old entry if it isn't supplied.
                // It isn't supplied in cases where we are *unsetting* a value 
                // (e.g. ClearValue, style unapply, trigger unapply)
                oldEntry = GetValueEntry(
                                    entryIndex,
                                    dp, 
                                    metadata,
                                    RequestFlags.RawEntry); 
            } 

            object oldValue = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; 


            /*
            if( TraceDependencyProperty.IsEnabled ) 
            {
                TraceDependencyProperty.Trace( 
                    TraceEventType.Verbose, 
                    TraceDependencyProperty.UpdateEffectiveValueStart,
                    this, 
                    dp,
                    dp.OwnerType,
                    oldValue,
                    oldEntry.BaseValueSourceInternal ); 
            }
            */ 
 
            // for control-value coercion, extract the desired control value, then
            // reset the new entry to ask for a re-evaluation with coercion 
            object controlValue = null;
            if (coerceWithCurrentValue)
            {
                controlValue = newEntry.Value; 
                newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced);
            } 
 
            // check for early-out opportunities:
            //  1) the new entry is of lower priority than the current entry 
            if ((newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Unknown) &&
                (newEntry.BaseValueSourceInternal < oldEntry.BaseValueSourceInternal))
            {
                return 0; 
            }
 
            bool isReEvaluate = false; 
            bool isCoerceValue = false;
            bool isClearValue = false; 

            if (newEntry.Value == DependencyProperty.UnsetValue)
            {
                FullValueSource fullValueSource = newEntry.FullValueSource; 
                isCoerceValue = (fullValueSource == FullValueSource.IsCoerced);
                isReEvaluate = true; 
 
                if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Local)
                { 
                    isClearValue = true;
                }
            }
 
            // if we're not in an animation update (caused by AnimationStorage.OnCurrentTimeInvalidated)
            // then always force a re-evaluation if (a) there was an animation in play or (b) there's 
            // an expression evaluation to be made 
            if (isReEvaluate ||
                (!newEntry.IsAnimated && 
                 (oldEntry.IsAnimated ||
                 (oldEntry.IsExpression && newEntry.IsExpression && (newEntry.ModifiedValue.BaseValue == oldEntry.ModifiedValue.BaseValue)))))
            {
                // we have to compute the new value 
                if (!isCoerceValue)
                { 
                    newEntry = EvaluateEffectiveValue(entryIndex, dp, metadata, oldEntry, newEntry, operationType); 

                    // Make sure that the call out did not cause a change to entryIndex 
                    entryIndex = CheckEntryIndex(entryIndex, targetIndex);

                    bool found = (newEntry.Value != DependencyProperty.UnsetValue);
                    if (!found && metadata.IsInherited) 
                    {
                        DependencyObject inheritanceParent = InheritanceParent; 
                        if (inheritanceParent != null) 
                        {
                            // Fetch the IsDeferredValue flag from the InheritanceParent 
                            EntryIndex parentEntryIndex = inheritanceParent.LookupEntry(dp.GlobalIndex);
                            if (parentEntryIndex.Found)
                            {
                                found = true; 
                                newEntry = inheritanceParent._effectiveValues[parentEntryIndex.Index].GetFlattenedEntry(RequestFlags.FullyResolved);
                                newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; 
                            } 
                        }
                    } 

                    // interesting that I just had to add this ... suggests that we are now overinvalidating
                    if (!found)
                    { 
                        newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
                    } 
                } 
                else
                { 
                    if (!oldEntry.HasModifiers)
                    {
                        newEntry = oldEntry;
                    } 
                    else
                    { 
                        newEntry = new EffectiveValueEntry(dp, oldEntry.BaseValueSourceInternal); 
                        ModifiedValue modifiedValue = oldEntry.ModifiedValue;
                        object baseValue = modifiedValue.BaseValue; 
                        newEntry.Value = baseValue;
                        newEntry.HasExpressionMarker = oldEntry.HasExpressionMarker;

                        if (oldEntry.IsExpression) 
                        {
                            newEntry.SetExpressionValue(modifiedValue.ExpressionValue, baseValue); 
                        } 

                        if (oldEntry.IsAnimated) 
                        {
                            newEntry.SetAnimatedValue(modifiedValue.AnimatedValue, baseValue);
                        }
                    } 
                }
            } 
 
            // Coerce to current value
            if (coerceWithCurrentValue) 
            {
                object baseValue = newEntry.GetFlattenedEntry(RequestFlags.CoercionBaseValue).Value;

                ProcessCoerceValue( 
                    dp,
                    metadata, 
                    ref entryIndex, 
                    ref targetIndex,
                    ref newEntry, 
                    ref oldEntry,
                    ref oldValue,
                    baseValue,
                    controlValue, 
                    null /*coerceValueCallback */,
                    coerceWithDeferredReference, 
                    coerceWithCurrentValue, 
                    false /*skipBaseValueChecks*/);
 
                // Make sure that the call out did not cause a change to entryIndex
                entryIndex = CheckEntryIndex(entryIndex, targetIndex);
            }
 
            // Coerce Value
            if (metadata.CoerceValueCallback != null && 
                !(isClearValue && newEntry.FullValueSource == (FullValueSource)BaseValueSourceInternal.Default)) 
            {
                // CALLBACK 
                object baseValue = newEntry.GetFlattenedEntry(RequestFlags.CoercionBaseValue).Value;

                ProcessCoerceValue(
                    dp, 
                    metadata,
                    ref entryIndex, 
                    ref targetIndex, 
                    ref newEntry,
                    ref oldEntry, 
                    ref oldValue,
                    baseValue,
                    null /* controlValue */,
                    metadata.CoerceValueCallback, 
                    coerceWithDeferredReference,
                    false /* coerceWithCurrentValue */, 
                    false /*skipBaseValueChecks*/); 

                // Make sure that the call out did not cause a change to entryIndex 
                entryIndex = CheckEntryIndex(entryIndex, targetIndex);
            }

            // The main difference between this callback and the metadata.CoerceValueCallback is that 
            // designers want to be able to coerce during all value changes including a change to the
            // default value. Whereas metadata.CoerceValueCallback coerces all property values but the 
            // default, because default values are meant to fit automatically fit into the coersion constraint. 

            if (dp.DesignerCoerceValueCallback != null) 
            {
                // During a DesignerCoerceValueCallback the value obtained is stored in the same
                // member as the metadata.CoerceValueCallback. In this case we do not store the
                // baseValue in the entry. Thus the baseValue checks will the violated. That is the 
                // reason for skipping these checks in this one case.
 
                // Also before invoking the DesignerCoerceValueCallback the baseValue must 
                // always be expanded if it is a DeferredReference
 
                ProcessCoerceValue(
                    dp,
                    metadata,
                    ref entryIndex, 
                    ref targetIndex,
                    ref newEntry, 
                    ref oldEntry, 
                    ref oldValue,
                    newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value, 
                    null /*controlValue*/,
                    dp.DesignerCoerceValueCallback,
                    false /*coerceWithDeferredReference*/,
                    false /*coerceWithCurrentValue*/, 
                    true /*skipBaseValueChecks*/);
 
                // Make sure that the call out did not cause a change to entryIndex 
                entryIndex = CheckEntryIndex(entryIndex, targetIndex);
            } 

            UpdateResult result = 0;

            if (newEntry.FullValueSource != (FullValueSource) BaseValueSourceInternal.Default) 
            {
                Debug.Assert(newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Unknown, "Value source should be known at this point"); 
                bool unsetValue = false; 

                if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Inherited) 
                {
                    if (DependencyObject.IsTreeWalkOperation(operationType) &&
                        (newEntry.IsCoerced || newEntry.IsAnimated))
                    { 
                        // an inherited value has been coerced or animated.  This
                        // should be treated as a new "set" of the property. 
                        // The current tree walk should not continue into the subtree, 
                        // but rather a new tree walk should start.
 
                        // this signals OnPropertyChanged to start a new tree walk
                        // and mark the current node as SelfInheritanceParent
                        operationType = OperationType.Unknown;
 
                        // this signals the caller not to continue the current
                        // tree walk into the subtree 
                        result |= UpdateResult.InheritedValueOverridden; 
                    }
                    else if (!IsSelfInheritanceParent) 
                    {
                        // otherwise, just inherit the value from the InheritanceParent
                        unsetValue = true;
                    } 
                }
 
                if (unsetValue) 
                {
                    UnsetEffectiveValue(entryIndex, dp, metadata); 
                }
                else
                {
                    SetEffectiveValue(entryIndex, dp, metadata, newEntry, oldEntry); 
                }
            } 
            else 
            {
                UnsetEffectiveValue(entryIndex, dp, metadata); 
            }

            // Change notifications are fired when the value actually changed or in
            // the case of the Freezable mutable factories when the value source changes. 
            // Try AvaCop without the second condition to repro this problem.
            bool isAValueChange = !Equals(dp, oldValue, newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value); 
 
            if (isAValueChange)
            { 
                result |= UpdateResult.ValueChanged;
            }

            if (isAValueChange || 
                (operationType == OperationType.ChangeMutableDefaultValue && oldEntry.BaseValueSourceInternal != newEntry.BaseValueSourceInternal) ||
                (metadata.IsInherited && oldEntry.BaseValueSourceInternal != newEntry.BaseValueSourceInternal && operationType != OperationType.AddChild && operationType != OperationType.RemoveChild && operationType != OperationType.Inherit)) 
            { 
                result |= UpdateResult.NotificationSent;
 
                try
                {
                    // fire change notification
                    NotifyPropertyChange( 
                            new DependencyPropertyChangedEventArgs(
                                    dp, 
                                    metadata, 
                                    isAValueChange,
                                    oldEntry, 
                                    newEntry,
                                    operationType));
                }
                finally 
                {
#if NESTED_OPERATIONS_CHECK 
                    NestedOperations--; 
#endif
                } 
            }

#region EventTracing
#if VERBOSE_PROPERTY_EVENT 
            if (isDynamicTracing)
            { 
                if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, MS.Utility.EventType.EndEvent); 
                }
            }
#endif
#endregion EventTracing 

 
            /* 
            if( TraceDependencyProperty.IsEnabled )
            { 
                TraceDependencyProperty.Trace(
                    TraceEventType.Verbose,
                    TraceDependencyProperty.UpdateEffectiveValueStop,
                    this, dp, dp.OwnerType, 
                    newEntry.Value, newEntry.BaseValueSourceInternal );
            } 
            */ 

            // There are two cases in which we need to adjust inheritance contexts: 
            //
            //     1.  The value pointed to this DP has changed, in which case
            //         we need to move the context from the old value to the
            //         new value. 
            //
            //     2.  The value has not changed, but the ValueSource for the 
            //         property has.  (For example, we've gone from being a local 
            //         value to the result of a binding expression that just
            //         happens to return the same DO instance.)  In which case 
            //         we may need to add or remove contexts even though we
            //         did not raise change notifications.
            //
            // We don't want to provide an inheritance context if the entry is 
            // animated, coerced, is an expression, is coming from a style or
            // template, etc.  To avoid this, we explicitly check that the 
            // FullValueSource is Local.  By checking FullValueSource rather than 
            // BaseValueSource we are implicitly filtering out any sources which
            // have modifiers.  (e.g., IsExpression, IsAnimated, etc.) 

            bool oldEntryHadContext = oldEntry.FullValueSource == (FullValueSource) BaseValueSourceInternal.Local;
            bool newEntryNeedsContext = newEntry.FullValueSource == (FullValueSource) BaseValueSourceInternal.Local;
 
            // NOTE:  We use result rather than isAValueChange below so that we
            //        pick up mutable default promotion, etc. 
            if (result != 0 || (oldEntryHadContext != newEntryNeedsContext)) 
            {
                if (oldEntryHadContext) 
                {
                    // RemoveSelfAsInheritanceContext no-ops null, non-DO values, etc.
                    RemoveSelfAsInheritanceContext(oldEntry.LocalValue, dp);
                } 

                // Become the context for the new value. This is happens after 
                // invalidation so that FE has a chance to hookup the logical 
                // tree first. This is done only if the current DependencyObject
                // wants to be in the InheritanceContext tree. 
                if (newEntryNeedsContext)
                {
                    // ProvideSelfAsInheritanceContext no-ops null, non-DO values, etc.
                    ProvideSelfAsInheritanceContext(newEntry.LocalValue, dp); 
                }
 
                // DANGER:  Callout might add/remove entries in the effective value table. 
                //          Uncomment the following if you need to use entryIndex post
                //          context hookup. 
                //
                // entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
            }
 
            return result;
        } 
Пример #16
0
        /// <summary>
        ///     This overload of GetValue assumes that entryIndex is valid. 
        ///      It also does not do the check storage on the InheritanceParent.
        /// </summary> 
        private EffectiveValueEntry GetEffectiveValue( 
            EntryIndex          entryIndex,
            DependencyProperty  dp, 
            RequestFlags        requests)
        {
            EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
            EffectiveValueEntry effectiveEntry = entry.GetFlattenedEntry(requests); 

            if (((requests & (RequestFlags.DeferredReferences | RequestFlags.RawEntry)) != 0) || !effectiveEntry.IsDeferredReference) 
            { 
                return effectiveEntry;
            } 

            if (!entry.HasModifiers)
            {
                // For thread-safety, sealed DOs can't modify _effectiveValues. 
                Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
 
                if (!entry.HasExpressionMarker) 
                {
                    // The value for this property was meant to come from a dictionary 
                    // and the creation of that value had been deferred until this
                    // time for better performance. Now is the time to actually instantiate
                    // this value by querying it from the dictionary. Once we have the
                    // value we can actually replace the deferred reference marker 
                    // with the actual value.
                    DeferredReference reference = (DeferredReference)entry.Value; 
                    object value = reference.GetValue(entry.BaseValueSourceInternal); 

                    if (!dp.IsValidValue(value)) 
                    {
                        throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
                    }
 
                    // Make sure the entryIndex is in [....] after
                    // the inflation of the deferred reference. 
                    entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); 

                    entry.Value = value; 

                    _effectiveValues[entryIndex.Index] = entry;
                    return entry;
                } 
            }
            else 
            { 
                // The value for this property was meant to come from a dictionary
                // and the creation of that value had been deferred until this 
                // time for better performance. Now is the time to actually instantiate
                // this value by querying it from the dictionary. Once we have the
                // value we can actually replace the deferred reference marker
                // with the actual value. 

                ModifiedValue modifiedValue = entry.ModifiedValue; 
                DeferredReference reference = null; 
                bool referenceFromExpression = false;
 
                if (entry.IsCoercedWithCurrentValue)
                {
                    if (!entry.IsAnimated)
                    { 
                        reference = modifiedValue.CoercedValue as DeferredReference;
                    } 
                } 

                if (reference == null && entry.IsExpression) 
                {
                    if (!entry.IsAnimated && !entry.IsCoerced)
                    {
                        reference = (DeferredReference) modifiedValue.ExpressionValue; 
                        referenceFromExpression = true;
                    } 
                } 

                Debug.Assert(reference != null, "the only modified values that can have deferredreferences are (a) expression, (b) coerced control value"); 
                if (reference == null)
                {
                    return effectiveEntry;
                } 

                object value = reference.GetValue(entry.BaseValueSourceInternal); 
 
                if (!dp.IsValidValue(value))
                { 
                    throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
                }

                // Make sure the entryIndex is in [....] after 
                // the inflation of the deferred reference.
                entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); 
 
                if (referenceFromExpression)
                { 
                    entry.SetExpressionValue(value, modifiedValue.BaseValue);
                }
                else
                { 
                    entry.SetCoercedValue(value, null, true /* skipBaseValueChecks */, entry.IsCoercedWithCurrentValue);
                } 
 
                _effectiveValues[entryIndex.Index] = entry;
 
                effectiveEntry.Value = value;
            }
            return effectiveEntry;
        } 
Пример #17
0
        private void ProcessCoerceValue(
            DependencyProperty dp, 
            PropertyMetadata metadata,
            ref EntryIndex entryIndex,
            ref int targetIndex,
            ref EffectiveValueEntry newEntry, 
            ref EffectiveValueEntry oldEntry,
            ref object oldValue, 
            object baseValue, 
            object controlValue,
            CoerceValueCallback coerceValueCallback, 
            bool coerceWithDeferredReference,
            bool coerceWithCurrentValue,
            bool skipBaseValueChecks)
        { 
            if (newEntry.IsDeferredReference)
            { 
                Debug.Assert(!(newEntry.IsCoerced && !newEntry.IsCoercedWithCurrentValue) && 
                    !newEntry.IsAnimated, "Coerced or Animated value cannot be a deferred reference");
 
                // Allow values to stay deferred through coercion callbacks in
                // limited circumstances, when we know the listener is internal.
                // Since we never assign DeferredReference instances to
                // non-internal (non-friend assembly) classes, it's safe to skip 
                // the dereference if the callback is to the DP owner (and not
                // a derived type).  This is consistent with passing raw 
                // DeferredReference instances to ValidateValue callbacks, which 
                // only ever go to the owner class.
                if (!coerceWithDeferredReference || 
                    dp.OwnerType != metadata.CoerceValueCallback.Method.DeclaringType) // Need 2nd check to rule out derived class callback overrides.
                {
                    // Resolve deferred references because we need the actual
                    // baseValue to evaluate the correct animated value. This is done 
                    // by invoking GetValue for this property.
                    DeferredReference dr = (DeferredReference) baseValue; 
                    baseValue = dr.GetValue(newEntry.BaseValueSourceInternal); 

                    // Set the baseValue back into the entry 
                    newEntry.SetCoersionBaseValue(baseValue);

                    entryIndex = CheckEntryIndex(entryIndex, targetIndex);
                } 
            }
 
            object coercedValue = coerceWithCurrentValue ? controlValue : coerceValueCallback(this, baseValue); 

            // Make sure that the call out did not cause a change to entryIndex 
            entryIndex = CheckEntryIndex(entryIndex, targetIndex);

            // Even if we used the controlValue in the coerce callback, we still want to compare against the original baseValue
            // to determine if we need to set a coerced value. 
            if (!Equals(dp, coercedValue, baseValue))
            { 
                // returning DependencyProperty.UnsetValue from a Coercion callback means "don't do the set" ... 
                // or "use previous value"
                if (coercedValue == DependencyProperty.UnsetValue) 
                {
                    if (oldEntry.IsDeferredReference)
                    {
                        DeferredReference reference = (DeferredReference)oldValue; 
                        oldValue = reference.GetValue(oldEntry.BaseValueSourceInternal);
 
                        entryIndex = CheckEntryIndex(entryIndex, targetIndex); 
                    }
 
                    coercedValue = oldValue;
                }

                // Note that we do not support the value being coerced to a 
                // DeferredReference
                if (!dp.IsValidValue(coercedValue)) 
                { 
                    // well... unless it's the control's "current value"
                    if (!(coerceWithCurrentValue && coercedValue is DeferredReference)) 
                        throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, coercedValue, dp.Name));
                }

                // Set the coerced value here. All other values would 
                // have been set during EvaluateEffectiveValue/GetValueCore.
 
                newEntry.SetCoercedValue(coercedValue, baseValue, skipBaseValueChecks, coerceWithCurrentValue); 
            }
        } 
Пример #18
0
        internal void SetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry newEntry, EffectiveValueEntry oldEntry) 
        {
            if (metadata != null && 
                metadata.IsInherited && 
                (newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Inherited ||
                    newEntry.IsCoerced || newEntry.IsAnimated) && 
                !IsSelfInheritanceParent)
            {
                SetIsSelfInheritanceParent();
                entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); 
            }
 
            bool restoreMarker = false; 

            if (oldEntry.HasExpressionMarker && !newEntry.HasExpressionMarker) 
            {
                BaseValueSourceInternal valueSource = newEntry.BaseValueSourceInternal;
                restoreMarker = (valueSource == BaseValueSourceInternal.ThemeStyle ||
                                 valueSource == BaseValueSourceInternal.ThemeStyleTrigger || 
                                 valueSource == BaseValueSourceInternal.Style ||
                                 valueSource == BaseValueSourceInternal.TemplateTrigger || 
                                 valueSource == BaseValueSourceInternal.StyleTrigger || 
                                 valueSource == BaseValueSourceInternal.ParentTemplate ||
                                 valueSource == BaseValueSourceInternal.ParentTemplateTrigger); 
            }

            if (restoreMarker)
            { 
                newEntry.RestoreExpressionMarker();
            } 
            else if (oldEntry.IsExpression && oldEntry.ModifiedValue.ExpressionValue == Expression.NoValue) 
            {
                // we now have a value for an expression that is "hiding" - save it 
                // as the expression value
                newEntry.SetExpressionValue(newEntry.Value, oldEntry.ModifiedValue.BaseValue);
            }
 
#if DEBUG
            object baseValue; 
            if (!newEntry.HasModifiers) 
            {
                baseValue = newEntry.Value; 
            }
            else
            {
                if (newEntry.IsCoercedWithCurrentValue) 
                {
                    baseValue = newEntry.ModifiedValue.CoercedValue; 
                } 
                else if (newEntry.IsExpression)
                { 
                    baseValue = newEntry.ModifiedValue.ExpressionValue;
                }
                else
                { 
                    baseValue = newEntry.ModifiedValue.BaseValue;
                } 
            } 

            Debug.Assert(newEntry.IsDeferredReference == (baseValue is DeferredReference)); 
#endif

            if (entryIndex.Found)
            { 
                _effectiveValues[entryIndex.Index] = newEntry;
            } 
            else 
            {
                InsertEntry(newEntry, entryIndex.Index); 
                if (metadata != null && metadata.IsInherited)
                {
                    InheritableEffectiveValuesCount++;
                } 
            }
 
            Debug.Assert(dp == null || (dp.GlobalIndex == newEntry.PropertyIndex), "EffectiveValueEntry & DependencyProperty do not match"); 
        }
Пример #19
0
        private EffectiveValueEntry EvaluateExpression( 
            EntryIndex entryIndex,
            DependencyProperty dp, 
            Expression expr,
            PropertyMetadata metadata,
            EffectiveValueEntry oldEntry,
            EffectiveValueEntry newEntry) 
        {
            object value = expr.GetValue(this, dp); 
            bool isDeferredReference = false; 

            if (value != DependencyProperty.UnsetValue && value != Expression.NoValue) 
            {
                isDeferredReference = (value is DeferredReference);
                if (!isDeferredReference && !dp.IsValidValue(value))
                { 
#region EventTracing
#if VERBOSE_PROPERTY_EVENT 
                    if (isDynamicTracing) 
                    {
                        if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) 
                        {
                            EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYGUID,
                                                                MS.Utility.EventType.EndEvent,
                                                                EventTrace.PROPERTYVALIDATION, 0xFFF ); 
                        }
                    } 
#endif 
#endregion EventTracing
                    throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name)); 
                }
            }
            else
            { 
                if (value == Expression.NoValue)
                { 
                    // The expression wants to "hide".  First set the 
                    // expression value to NoValue to indicate "hiding".
                    newEntry.SetExpressionValue(Expression.NoValue, expr); 

                    // Next, get the expression value some other way.
                    if (!dp.ReadOnly)
                    { 
                        EvaluateBaseValueCore(dp, metadata, ref newEntry);
                        value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; 
                    } 
                    else
                    { 
                        value = DependencyProperty.UnsetValue;
                    }
                }
 
                // if there is still no value, use the default
                if (value == DependencyProperty.UnsetValue) 
                { 
                    value = metadata.GetDefaultValue(this, dp);
                } 
            }

            // Set the expr and its evaluated value into
            // the _effectiveValues cache 
            newEntry.SetExpressionValue(value, expr);
            return newEntry; 
        } 
Пример #20
0
 // 
 //  This method
 //  1. Removes the entry if there is one with valueSource >= the specified 
 // 
 internal void UnsetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata)
 { 
     if (entryIndex.Found)
     {
         RemoveEntry(entryIndex.Index, dp);
         if (metadata != null && metadata.IsInherited) 
         {
             InheritableEffectiveValuesCount--; 
         } 
     }
 } 
Пример #21
0
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        private EffectiveValueEntry EvaluateEffectiveValue(
            EntryIndex entryIndex,
            DependencyProperty dp,
            PropertyMetadata metadata, 
            EffectiveValueEntry oldEntry,
            EffectiveValueEntry newEntry, // this is only used to recognize if this is a clear local value 
            OperationType operationType) 
        {
#region EventTracing 
#if VERBOSE_PROPERTY_EVENT
            bool isDynamicTracing = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); // This was under "normal"
            if (isDynamicTracing)
            { 
                ++ValidationCount;
                if( ValidationCount % 100 == 0 ) 
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID,
                                                         MS.Utility.EventType.Info, 
                                                         ValidationCount );
                }

                string TypeAndName = String.Format(CultureInfo.InvariantCulture, "[{0}]{1}({2})",GetType().Name,dp.Name,base.GetHashCode());  // FxCop wanted the CultureInfo.InvariantCulture 

                EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID, 
                                                     MS.Utility.EventType.StartEvent, 
                                                     base.GetHashCode(), TypeAndName ); // base.GetHashCode() to avoid calling a virtual, which FxCop doesn't like.
            } 
#endif
#endregion EventTracing

#if NESTED_OPERATIONS_CHECK 
            // Are we validating out of control?
            if( NestedOperations > NestedOperationMaximum ) 
            { 
                // We're validating out of control, time to abort.
                throw new InvalidOperationException("Too many levels of nested DependencyProperty GetValue calls.  This usually indicates a circular reference in the application and the cycle needs to be broken."); 
            }
            NestedOperations++; // Decrement in the finally block
#endif
 
            object value = DependencyProperty.UnsetValue;
 
            try 
            {
                // Read local storage 
                bool isSetValue = (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Local);
                bool isClearLocalValue = isSetValue && (newEntry.Value == DependencyProperty.UnsetValue);
                bool oldLocalIsExpression = false;
 
                if (isClearLocalValue)
                { 
                    newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Unknown; 
                }
                else 
                {
                    // if we reached this on a re-evaluate of a setvalue, we need to make sure
                    // we don't lose track of the newly specified local value.
                    // for all other cases, the oldEntry will have the local value we should 
                    // use.
                    value = isSetValue ? newEntry.LocalValue : oldEntry.LocalValue; 
 
                    if (value == ExpressionInAlternativeStore)
                    { 
                        value = DependencyProperty.UnsetValue;
                    }
                    else
                    { 
                        oldLocalIsExpression = isSetValue ? newEntry.IsExpression : oldEntry.IsExpression;
                    } 
                } 

                // (If local storage not Unset and not an Expression, return) 
                if (value != DependencyProperty.UnsetValue)
                {
                    newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);
                    newEntry.Value = value; 

                    // Check if an Expression is set 
                    if (oldLocalIsExpression) 
                    {
                        // CALLBACK 
                        newEntry = EvaluateExpression(
                            entryIndex,
                            dp,
                            (Expression) value, 
                            metadata,
                            oldEntry, 
                            newEntry); 

                        entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); 

                        value = newEntry.ModifiedValue.ExpressionValue;
                    }
                } 

                // Subclasses are not allowed to resolve/modify the value for read-only properties. 
                if( !dp.ReadOnly ) 
                {
                    // Give subclasses a chance to resolve/modify the value 
                    EvaluateBaseValueCore(dp, metadata, ref newEntry);

                    // we need to have the default value in the entry before we do the animation check
                    if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) 
                    {
                        newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); 
                    } 

                    value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; 

                    entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);

                    if (oldEntry.IsAnimated) 
                    {
                        newEntry.ResetCoercedValue(); 
                        EvaluateAnimatedValueCore(dp, metadata, ref newEntry); 
                        value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value;
                    } 
                }
            }
            finally
            { 
#if NESTED_OPERATIONS_CHECK
                NestedOperations--; 
#endif 
            }
 
#region EventTracing
#if VERBOSE_PROPERTY_EVENT
            if (isDynamicTracing)
            { 
                if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose))
                { 
                    int UsingDefault = 1; 
                    if (value != DependencyProperty.UnsetValue)
                        UsingDefault = 0; 
                    EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID,
                                                         MS.Utility.EventType.EndEvent,
                                                         UsingDefault);
                } 
            }
#endif 
#endregion EventTracing 

            if (value == DependencyProperty.UnsetValue) 
            {
                newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
            }
 
            return newEntry;
        } 
Пример #22
0
        /// <summary> 
        ///     The common code shared by all variants of ClearValue 
        /// </summary>
        private void ClearValueCommon(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata) 
        {
            if (IsSealed)
            {
                throw new InvalidOperationException(SR.Get(SRID.ClearOnReadOnlyObjectNotAllowed, this)); 
            }
 
            // Get old value 
            EffectiveValueEntry oldEntry = GetValueEntry(
                                        entryIndex, 
                                        dp,
                                        metadata,
                                        RequestFlags.RawEntry);
 
            // Get current local value
            // (No need to go through read local callback, just checking 
            // for presence of Expression) 
            object current = oldEntry.LocalValue;
 
            // Get current expression
            Expression currentExpr = (oldEntry.IsExpression) ? (current as Expression) : null;

            // Inform value expression of detachment, if applicable 
            if (currentExpr != null)
            { 
                // CALLBACK 
                DependencySource[] currentSources = currentExpr.GetSources();
 
                UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false);  // Remove

                // CALLBACK
                currentExpr.OnDetach(this, dp); 
                currentExpr.MarkDetached();
                entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); 
            } 

            // valuesource == Local && value == UnsetValue indicates that we are clearing the local value 
            EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);

            // Property is now invalid
            UpdateEffectiveValue( 
                    entryIndex,
                    dp, 
                    metadata, 
                    oldEntry,
                    ref newEntry, 
                    false /* coerceWithDeferredReference */,
                    false /* coerceWithCurrentValue */,
                    OperationType.Unknown);
        } 
        private static bool DefaultFreezeValueCallback(
            DependencyObject d,
            DependencyProperty dp,
            EntryIndex entryIndex,
            PropertyMetadata metadata,
            bool isChecking)
        {
            // The expression check only needs to be done when isChecking is true
            // because if we return false here the Freeze() call will fail.
            if (isChecking)
            {
                if (d.HasExpression(entryIndex, dp))
                {
                    if (TraceFreezable.IsEnabled)
                    {
                        TraceFreezable.Trace(
                            TraceEventType.Warning,
                            TraceFreezable.UnableToFreezeExpression,
                            d,
                            dp,
                            dp.OwnerType);
                    }

                    return(false);
                }
            }

            if (!dp.IsValueType)
            {
                object value =
                    d.GetValueEntry(
                        entryIndex,
                        dp,
                        metadata,
                        RequestFlags.FullyResolved).Value;

                if (value != null)
                {
                    Freezable valueAsFreezable = value as Freezable;

                    if (valueAsFreezable != null)
                    {
                        if (!valueAsFreezable.Freeze(isChecking))
                        {
                            if (TraceFreezable.IsEnabled)
                            {
                                TraceFreezable.Trace(
                                    TraceEventType.Warning,
                                    TraceFreezable.UnableToFreezeFreezableSubProperty,
                                    d,
                                    dp,
                                    dp.OwnerType);
                            }

                            return(false);
                        }
                    }
                    else  // not a Freezable
                    {
                        DispatcherObject valueAsDispatcherObject = value as DispatcherObject;

                        if (valueAsDispatcherObject != null)
                        {
                            if (valueAsDispatcherObject.Dispatcher == null)
                            {
                                // The property is a free-threaded DispatcherObject; since it's
                                // already free-threaded it doesn't prevent this Freezable from
                                // becoming free-threaded too.
                                // It is up to the creator of this type to ensure that the
                                // DispatcherObject is actually immutable
                            }
                            else
                            {
                                // The value of this property derives from DispatcherObject and
                                // has thread affinity; return false.

                                if (TraceFreezable.IsEnabled)
                                {
                                    TraceFreezable.Trace(
                                        TraceEventType.Warning,
                                        TraceFreezable.UnableToFreezeDispatcherObjectWithThreadAffinity,
                                        d,
                                        dp,
                                        dp.OwnerType,
                                        valueAsDispatcherObject);
                                }

                                return(false);
                            }
                        }

                        // The property isn't a DispatcherObject.  It may be immutable (such as a string)
                        // or the user may have made it thread-safe.  It's up to the creator of the type to
                        // do the right thing; we return true as an extensibility point.
                    }
                }
            }

            return(true);
        }