EffectiveValueEntry.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / System / Windows / EffectiveValueEntry.cs / 1305600 / EffectiveValueEntry.cs

                            /****************************************************************************\ 
*
* File: EffectiveValueEntry.cs
*
*  This file describes an entry in the EffectiveValues list held by a 
*  DependencyObject.
* 
* Copyright (C) 2005 by Microsoft Corporation.  All rights reserved. 
*
\***************************************************************************/ 

using MS.Internal.WindowsBase;  // FriendAccessAllowed
using System.Collections;       // IDictionary
using System.Diagnostics;       // Debug.Assert 

namespace System.Windows 
{ 
    [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    internal struct EffectiveValueEntry 
    {
        #region InternalMethods

        internal static EffectiveValueEntry CreateDefaultValueEntry(DependencyProperty dp, object value) 
        {
            EffectiveValueEntry entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default); 
            entry.Value = value; 
            return entry;
 
        }

        internal EffectiveValueEntry(DependencyProperty dp)
        { 
            _propertyIndex = (short) dp.GlobalIndex;
            _value = null; 
            _source = (FullValueSource) BaseValueSourceInternal.Unknown; 
        }
 
        internal EffectiveValueEntry(DependencyProperty dp, BaseValueSourceInternal valueSource)
        {
            _propertyIndex = (short) dp.GlobalIndex;
            _value = DependencyProperty.UnsetValue; 
            _source = (FullValueSource) valueSource;
        } 
 
        internal EffectiveValueEntry(DependencyProperty dp, FullValueSource fullValueSource)
        { 
            _propertyIndex = (short) dp.GlobalIndex;
            _value = DependencyProperty.UnsetValue;
            _source = fullValueSource;
        } 

        internal void SetExpressionValue(object value, object baseValue) 
        { 
            Debug.Assert(value != DependencyProperty.UnsetValue);
 
            ModifiedValue modifiedValue = EnsureModifiedValue();
            modifiedValue.ExpressionValue = value;
            IsExpression = true;
            IsDeferredReference = value is DeferredReference; 

            Debug.Assert(Object.Equals(modifiedValue.BaseValue, baseValue)); 
            Debug.Assert(!(baseValue is DeferredReference)); 
            Debug.Assert(IsDeferredReference == (value is DeferredReference));
        } 

        internal void SetAnimatedValue(object value, object baseValue)
        {
            Debug.Assert((value != DependencyProperty.UnsetValue) && 
                         !(value is DeferredReference));
 
            ModifiedValue modifiedValue = EnsureModifiedValue(); 
            modifiedValue.AnimatedValue = value;
            IsAnimated = true; 

            // Animated values should never be deferred
            IsDeferredReference = false;
 
            Debug.Assert(!(modifiedValue.AnimatedValue is DeferredReference));
            Debug.Assert(Object.Equals(modifiedValue.BaseValue, baseValue) || 
                         Object.Equals(modifiedValue.ExpressionValue, baseValue)); 
            Debug.Assert(!(baseValue is DeferredReference) &&
                         ! (modifiedValue.BaseValue is DeferredReference) && 
                         ! (modifiedValue.ExpressionValue is DeferredReference));
        }

        internal void SetCoercedValue(object value, object baseValue, bool skipBaseValueChecks, bool coerceWithCurrentValue) 
        {
            Debug.Assert(value != DependencyProperty.UnsetValue && 
                         !((value is DeferredReference) && !coerceWithCurrentValue)); 

            // if this is already a CoercedWithControlValue entry, we are applying a 
            // second coercion (e.g. from the CoerceValueCallback).  The baseValue
            // passed in is the result of the control-value coercion, but for the
            // purposes of this method we should use the original base value instead.
            if (IsCoercedWithCurrentValue) 
            {
                baseValue = ModifiedValue.BaseValue; 
            } 

            ModifiedValue modifiedValue = EnsureModifiedValue(); 
            modifiedValue.CoercedValue = value;
            IsCoerced = true;
            IsCoercedWithCurrentValue = coerceWithCurrentValue;
 
            // The only CoercedValues that can be deferred are Control values.
            if (coerceWithCurrentValue) 
            { 
                IsDeferredReference = (value is DeferredReference);
            } 
            else
            {
                IsDeferredReference = false;
            } 

 
            Debug.Assert(skipBaseValueChecks || 
                         Object.Equals(modifiedValue.BaseValue, baseValue) ||
                         Object.Equals(modifiedValue.ExpressionValue, baseValue) || 
                         Object.Equals(modifiedValue.AnimatedValue, baseValue));
            Debug.Assert(!(baseValue is DeferredReference) &&
                         ! (modifiedValue.BaseValue is DeferredReference) &&
                         ! (modifiedValue.ExpressionValue is DeferredReference) && 
                         ! (modifiedValue.AnimatedValue is DeferredReference));
        } 
 
        internal void ResetAnimatedValue()
        { 
            if (IsAnimated)
            {
                ModifiedValue modifiedValue = ModifiedValue;
                modifiedValue.AnimatedValue = null; 
                IsAnimated = false;
 
                if (!HasModifiers) 
                {
                    Value = modifiedValue.BaseValue; 
                }
                else
                {
                    // The setter takes care of the IsDeferred flag no need to compute it twice. 
                    ComputeIsDeferred();
                } 
            } 
        }
 
        internal void ResetCoercedValue()
        {
            if (IsCoerced)
            { 
                ModifiedValue modifiedValue = ModifiedValue;
                modifiedValue.CoercedValue = null; 
                IsCoerced = false; 

                if (!HasModifiers) 
                {
                    Value = modifiedValue.BaseValue;
                }
                else 
                {
                    ComputeIsDeferred(); 
                } 
            }
        } 

        // remove all modifiers, retain value source, and set value to supplied value
        internal void ResetValue(object value, bool hasExpressionMarker)
        { 
            _source &= FullValueSource.ValueSourceMask;
            _value = value; 
            if (hasExpressionMarker) 
            {
                HasExpressionMarker = true; 
            }
            else
            {
                ComputeIsDeferred(); 
            }
            Debug.Assert(hasExpressionMarker == (value == DependencyObject.ExpressionInAlternativeStore), "hasExpressionMarker flag must match value"); 
        } 

        // add an expression marker back as the base value for an expression value 
        internal void RestoreExpressionMarker()
        {
            if (HasModifiers)
            { 
                ModifiedValue entry = ModifiedValue;
                entry.ExpressionValue = entry.BaseValue; 
                entry.BaseValue = DependencyObject.ExpressionInAlternativeStore; 
                _source |= FullValueSource.IsExpression | FullValueSource.HasExpressionMarker;
 
                //recompute the isDeferredReference flag as it may have changed
                ComputeIsDeferred();
            }
            else 
            {
                object value = Value; 
                Value = DependencyObject.ExpressionInAlternativeStore; 
                SetExpressionValue(value, DependencyObject.ExpressionInAlternativeStore);
                _source |= FullValueSource.HasExpressionMarker; 
            }


        } 

        // Computes and set the IsDeferred hint flag. 
        // This take into account all flags and should only be used sparingly. 
        private void ComputeIsDeferred()
        { 
            bool isDeferredReference = false;
            if (!HasModifiers)
            {
                isDeferredReference = Value is DeferredReference; 
            }
            else if (ModifiedValue != null) 
            { 
                if (IsCoercedWithCurrentValue)
                { 
                    isDeferredReference = ModifiedValue.CoercedValue is DeferredReference;
                }
                else if (IsExpression)
                { 
                    isDeferredReference = ModifiedValue.ExpressionValue is DeferredReference;
                } 
 
                // For animated values isDeferred will always be false.
            } 

            IsDeferredReference = isDeferredReference;
        }
 

        #endregion InternalMethods 
 
        #region InternalProperties
 
        public int PropertyIndex
        {
            get { return _propertyIndex; }
            set { _propertyIndex = (short)value; } 
        }
 
        ///  
        ///     If HasModifiers is true then it holds the value
        ///     else it holds the modified value instance 
        /// 
        internal object Value
        {
            get { return _value; } 
            set {
                _value = value; 
                IsDeferredReference = value is DeferredReference; 
                Debug.Assert(value is DeferredReference == IsDeferredReference);
            } 
        }

        internal BaseValueSourceInternal BaseValueSourceInternal
        { 
            get { return (BaseValueSourceInternal)(_source & FullValueSource.ValueSourceMask); }
            set { _source = (_source & ~FullValueSource.ValueSourceMask) | (FullValueSource)value; } 
        } 

        internal bool IsDeferredReference 
        {
            get
            {
                // When this flag is true we treat it as a hint rather than a guarantee and update 
                // it if is out of [....]. When the flag is false, however we expect it to guarantee
                // that the value isn't a DeferredReference. 
 
                bool isDeferredReference = ReadPrivateFlag(FullValueSource.IsPotentiallyADeferredReference);
                if (isDeferredReference) 
                {
                    // Check if the value is really a deferred reference
                    ComputeIsDeferred();
                    isDeferredReference = ReadPrivateFlag(FullValueSource.IsPotentiallyADeferredReference); 
                }
 
                return isDeferredReference; 
            }
 
            private set { WritePrivateFlag(FullValueSource.IsPotentiallyADeferredReference, value); }
        }

        internal bool IsExpression 
        {
            get { return ReadPrivateFlag(FullValueSource.IsExpression); } 
            private set { WritePrivateFlag(FullValueSource.IsExpression, value); } 
        }
 
        internal bool IsAnimated
        {
            get { return ReadPrivateFlag(FullValueSource.IsAnimated); }
            private set { WritePrivateFlag(FullValueSource.IsAnimated, value); } 
        }
 
        internal bool IsCoerced 
        {
            get { return ReadPrivateFlag(FullValueSource.IsCoerced); } 
            private set { WritePrivateFlag(FullValueSource.IsCoerced, value); }
        }

        internal bool HasModifiers 
        {
            get { return (_source & FullValueSource.ModifiersMask) != 0; } 
        } 

        internal FullValueSource FullValueSource 
        {
            get { return _source; }
        }
 

        internal bool HasExpressionMarker 
        { 
            get { return ReadPrivateFlag(FullValueSource.HasExpressionMarker); }
            set { WritePrivateFlag(FullValueSource.HasExpressionMarker, value); } 
        }

        internal bool IsCoercedWithCurrentValue
        { 
            get { return ReadPrivateFlag(FullValueSource.IsCoercedWithCurrentValue); }
            set { WritePrivateFlag(FullValueSource.IsCoercedWithCurrentValue, value); } 
        } 

        internal EffectiveValueEntry GetFlattenedEntry(RequestFlags requests) 
        {
            if ((_source & (FullValueSource.ModifiersMask | FullValueSource.HasExpressionMarker)) == 0)
            {
                // If the property does not have any modifiers 
                // then just return the base value.
                return this; 
            } 

            if (!HasModifiers) 
            {
                Debug.Assert(HasExpressionMarker);

                // This is the case when some one stuck an expression into 
                // an alternate store such as a style or a template but the
                // new value for the expression has not been evaluated yet. 
                // In the intermediate we need to return the default value 
                // for the property. This problem was manifested in DRTDocumentViewer.
                EffectiveValueEntry unsetEntry = new EffectiveValueEntry(); 
                unsetEntry.BaseValueSourceInternal = BaseValueSourceInternal;
                unsetEntry.PropertyIndex = PropertyIndex;
                return unsetEntry;
            } 

            // else entry has modifiers 
            EffectiveValueEntry entry = new EffectiveValueEntry(); 
            entry.BaseValueSourceInternal = BaseValueSourceInternal;
            entry.PropertyIndex = PropertyIndex; 
            entry.IsDeferredReference = IsDeferredReference;

            // If the property has a modifier return the modified value
            Debug.Assert(ModifiedValue != null); 

            // outside of DO, we flatten modified value 
            ModifiedValue modifiedValue = ModifiedValue; 

            // Note that the modified values have an order of precedence 
            // 1. Coerced Value (including Current value)
            // 2. Animated Value
            // 3. Expression Value
            // Also note that we support any arbitrary combinations of these 
            // modifiers and will yet the precedence metioned above.
            if (IsCoerced) 
            { 
                if ((requests & RequestFlags.CoercionBaseValue) == 0)
                { 
                    entry.Value = modifiedValue.CoercedValue;
                }
                else
                { 
                    // This is the case when CoerceValue tries to query
                    // the old base value for the property 
                    if (IsCoercedWithCurrentValue) 
                    {
                        entry.Value = modifiedValue.CoercedValue; 
                    }
                    else if (IsAnimated && ((requests & RequestFlags.AnimationBaseValue) == 0))
                    {
                        entry.Value = modifiedValue.AnimatedValue; 
                    }
                    else if (IsExpression) 
                    { 
                        entry.Value = modifiedValue.ExpressionValue;
                    } 
                    else
                    {
                        entry.Value = modifiedValue.BaseValue;
                    } 
                }
            } 
            else if (IsAnimated) 
            {
                if ((requests & RequestFlags.AnimationBaseValue) == 0) 
                {
                    entry.Value = modifiedValue.AnimatedValue;
                }
                else 
                {
                    // This is the case when [UI/Content]Element are 
                    // requesting the base value of an animation. 
                    if (IsExpression)
                    { 
                        entry.Value = modifiedValue.ExpressionValue;
                    }
                    else
                    { 
                        entry.Value = modifiedValue.BaseValue;
                     } 
                } 
            }
            else 
            {
                Debug.Assert(IsExpression == true);

                object expressionValue = modifiedValue.ExpressionValue; 

                entry.Value = expressionValue; 
            } 

            Debug.Assert(entry.IsDeferredReference == (entry.Value is DeferredReference), "Value and DeferredReference flag should be in [....]; hitting this may mean that it's time to divide the DeferredReference flag into a set of flags, one for each modifier"); 

            return entry;
        }
 
        internal void SetAnimationBaseValue(object animationBaseValue)
        { 
            if (!HasModifiers) 
            {
                Value = animationBaseValue; 
            }
            else
            {
                ModifiedValue modifiedValue = ModifiedValue; 

                if (IsExpression) 
                { 
                    modifiedValue.ExpressionValue = animationBaseValue;
                } 
                else
                {
                    modifiedValue.BaseValue = animationBaseValue;
                } 

                //the modified value may be a deferred reference so recompute this flag. 
                ComputeIsDeferred(); 
            }
        } 

        internal void SetCoersionBaseValue(object coersionBaseValue)
        {
            if (!HasModifiers) 
            {
                Value = coersionBaseValue; 
            } 
            else
            { 
                ModifiedValue modifiedValue = ModifiedValue;

                if (IsAnimated)
                { 
                    modifiedValue.AnimatedValue = coersionBaseValue;
                } 
                else if (IsExpression) 
                {
                    modifiedValue.ExpressionValue = coersionBaseValue; 
                }
                else
                {
                    modifiedValue.BaseValue = coersionBaseValue; 
                }
                //the modified value may be a deferred reference so recompute this flag. 
                ComputeIsDeferred(); 
            }
        } 

        internal object LocalValue
        {
            get 
            {
                if (BaseValueSourceInternal == BaseValueSourceInternal.Local) 
                { 
                    if (!HasModifiers)
                    { 
                        Debug.Assert(Value != DependencyProperty.UnsetValue);
                        return Value;
                    }
                    else 
                    {
                        Debug.Assert(ModifiedValue != null && ModifiedValue.BaseValue != DependencyProperty.UnsetValue); 
                        return ModifiedValue.BaseValue; 
                    }
                } 
                else
                {
                    return DependencyProperty.UnsetValue;
                } 
            }
 
            set 
            {
                Debug.Assert(BaseValueSourceInternal == BaseValueSourceInternal.Local, "This can happen only on an entry already having a local value"); 

                if (!HasModifiers)
                {
                    Debug.Assert(Value != DependencyProperty.UnsetValue); 
                    Value = value;
                } 
                else 
                {
                    Debug.Assert(ModifiedValue != null && ModifiedValue.BaseValue != DependencyProperty.UnsetValue); 
                    ModifiedValue.BaseValue = value;
                }
            }
        } 

        internal ModifiedValue ModifiedValue 
        { 
            get
            { 
                if (_value != null)
                {
                    return _value as ModifiedValue;
                } 
                return null;
            } 
        } 

        private ModifiedValue EnsureModifiedValue() 
        {
            ModifiedValue modifiedValue = null;
            if (_value == null)
            { 
                _value = modifiedValue = new ModifiedValue();
            } 
            else 
            {
                modifiedValue = _value as ModifiedValue; 
                if (modifiedValue == null)
                {
                    modifiedValue = new ModifiedValue();
                    modifiedValue.BaseValue = _value; 
                    _value = modifiedValue;
                } 
            } 
            return modifiedValue;
        } 

        internal void Clear()
        {
            _propertyIndex = -1; 
            _value = null;
            _source = 0; 
        } 

        #endregion InternalProperties 

        #region PrivateMethods

        private void WritePrivateFlag(FullValueSource bit, bool value) 
        {
            if (value) 
            { 
                _source |= bit;
            } 
            else
            {
                _source &= ~bit;
            } 
        }
 
        private bool ReadPrivateFlag(FullValueSource bit) 
        {
            return (_source & bit) != 0; 
        }

        #endregion PrivateMethods
 
        #region Data
 
        private object                      _value; 
        private short                       _propertyIndex;
        private FullValueSource             _source; 

        #endregion Data
    }
 

    [FriendAccessAllowed] // Built into Base, also used by Core & Framework. 
    internal enum FullValueSource : short 
    {
        // Bit used to store BaseValueSourceInternal = 0x01 
        // Bit used to store BaseValueSourceInternal = 0x02
        // Bit used to store BaseValueSourceInternal = 0x04
        // Bit used to store BaseValueSourceInternal = 0x08
 
        ValueSourceMask     = 0x000F,
        ModifiersMask       = 0x0070, 
        IsExpression        = 0x0010, 
        IsAnimated          = 0x0020,
        IsCoerced           = 0x0040, 
        IsPotentiallyADeferredReference = 0x0080,
        HasExpressionMarker = 0x0100,
        IsCoercedWithCurrentValue = 0x200,
    } 

    // Note that these enum values are arranged in the reverse order of 
    // precendence for these sources. Local value has highest 
    // precedence and Default value has the least. Note that we do not
    // store default values in the _effectiveValues cache unless it is 
    // being coerced/animated.
    [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    internal enum BaseValueSourceInternal : short
    { 
        Unknown                 = 0,
        Default                 = 1, 
        Inherited               = 2, 
        ThemeStyle              = 3,
        ThemeStyleTrigger       = 4, 
        Style                   = 5,
        TemplateTrigger         = 6,
        StyleTrigger            = 7,
        ImplicitReference       = 8, 
        ParentTemplate          = 9,
        ParentTemplateTrigger   = 10, 
        Local                   = 11, 
    }
 
    [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    internal class ModifiedValue
    {
        #region InternalProperties 

        internal object BaseValue 
        { 
            get { return _baseValue; }
            set { _baseValue = value; } 
        }

        internal object ExpressionValue
        { 
            get { return _expressionValue; }
            set { _expressionValue = value; } 
        } 

        internal object AnimatedValue 
        {
            get { return _animatedValue; }
            set { _animatedValue = value; }
        } 

        internal object CoercedValue 
        { 
            get { return _coercedValue; }
            set { _coercedValue = value; } 
        }

        #endregion InternalProperties
 
        #region Data
 
        private object _baseValue; 
        private object _expressionValue;
        private object _animatedValue; 
        private object _coercedValue;

        #endregion Data
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/****************************************************************************\ 
*
* File: EffectiveValueEntry.cs
*
*  This file describes an entry in the EffectiveValues list held by a 
*  DependencyObject.
* 
* Copyright (C) 2005 by Microsoft Corporation.  All rights reserved. 
*
\***************************************************************************/ 

using MS.Internal.WindowsBase;  // FriendAccessAllowed
using System.Collections;       // IDictionary
using System.Diagnostics;       // Debug.Assert 

namespace System.Windows 
{ 
    [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    internal struct EffectiveValueEntry 
    {
        #region InternalMethods

        internal static EffectiveValueEntry CreateDefaultValueEntry(DependencyProperty dp, object value) 
        {
            EffectiveValueEntry entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default); 
            entry.Value = value; 
            return entry;
 
        }

        internal EffectiveValueEntry(DependencyProperty dp)
        { 
            _propertyIndex = (short) dp.GlobalIndex;
            _value = null; 
            _source = (FullValueSource) BaseValueSourceInternal.Unknown; 
        }
 
        internal EffectiveValueEntry(DependencyProperty dp, BaseValueSourceInternal valueSource)
        {
            _propertyIndex = (short) dp.GlobalIndex;
            _value = DependencyProperty.UnsetValue; 
            _source = (FullValueSource) valueSource;
        } 
 
        internal EffectiveValueEntry(DependencyProperty dp, FullValueSource fullValueSource)
        { 
            _propertyIndex = (short) dp.GlobalIndex;
            _value = DependencyProperty.UnsetValue;
            _source = fullValueSource;
        } 

        internal void SetExpressionValue(object value, object baseValue) 
        { 
            Debug.Assert(value != DependencyProperty.UnsetValue);
 
            ModifiedValue modifiedValue = EnsureModifiedValue();
            modifiedValue.ExpressionValue = value;
            IsExpression = true;
            IsDeferredReference = value is DeferredReference; 

            Debug.Assert(Object.Equals(modifiedValue.BaseValue, baseValue)); 
            Debug.Assert(!(baseValue is DeferredReference)); 
            Debug.Assert(IsDeferredReference == (value is DeferredReference));
        } 

        internal void SetAnimatedValue(object value, object baseValue)
        {
            Debug.Assert((value != DependencyProperty.UnsetValue) && 
                         !(value is DeferredReference));
 
            ModifiedValue modifiedValue = EnsureModifiedValue(); 
            modifiedValue.AnimatedValue = value;
            IsAnimated = true; 

            // Animated values should never be deferred
            IsDeferredReference = false;
 
            Debug.Assert(!(modifiedValue.AnimatedValue is DeferredReference));
            Debug.Assert(Object.Equals(modifiedValue.BaseValue, baseValue) || 
                         Object.Equals(modifiedValue.ExpressionValue, baseValue)); 
            Debug.Assert(!(baseValue is DeferredReference) &&
                         ! (modifiedValue.BaseValue is DeferredReference) && 
                         ! (modifiedValue.ExpressionValue is DeferredReference));
        }

        internal void SetCoercedValue(object value, object baseValue, bool skipBaseValueChecks, bool coerceWithCurrentValue) 
        {
            Debug.Assert(value != DependencyProperty.UnsetValue && 
                         !((value is DeferredReference) && !coerceWithCurrentValue)); 

            // if this is already a CoercedWithControlValue entry, we are applying a 
            // second coercion (e.g. from the CoerceValueCallback).  The baseValue
            // passed in is the result of the control-value coercion, but for the
            // purposes of this method we should use the original base value instead.
            if (IsCoercedWithCurrentValue) 
            {
                baseValue = ModifiedValue.BaseValue; 
            } 

            ModifiedValue modifiedValue = EnsureModifiedValue(); 
            modifiedValue.CoercedValue = value;
            IsCoerced = true;
            IsCoercedWithCurrentValue = coerceWithCurrentValue;
 
            // The only CoercedValues that can be deferred are Control values.
            if (coerceWithCurrentValue) 
            { 
                IsDeferredReference = (value is DeferredReference);
            } 
            else
            {
                IsDeferredReference = false;
            } 

 
            Debug.Assert(skipBaseValueChecks || 
                         Object.Equals(modifiedValue.BaseValue, baseValue) ||
                         Object.Equals(modifiedValue.ExpressionValue, baseValue) || 
                         Object.Equals(modifiedValue.AnimatedValue, baseValue));
            Debug.Assert(!(baseValue is DeferredReference) &&
                         ! (modifiedValue.BaseValue is DeferredReference) &&
                         ! (modifiedValue.ExpressionValue is DeferredReference) && 
                         ! (modifiedValue.AnimatedValue is DeferredReference));
        } 
 
        internal void ResetAnimatedValue()
        { 
            if (IsAnimated)
            {
                ModifiedValue modifiedValue = ModifiedValue;
                modifiedValue.AnimatedValue = null; 
                IsAnimated = false;
 
                if (!HasModifiers) 
                {
                    Value = modifiedValue.BaseValue; 
                }
                else
                {
                    // The setter takes care of the IsDeferred flag no need to compute it twice. 
                    ComputeIsDeferred();
                } 
            } 
        }
 
        internal void ResetCoercedValue()
        {
            if (IsCoerced)
            { 
                ModifiedValue modifiedValue = ModifiedValue;
                modifiedValue.CoercedValue = null; 
                IsCoerced = false; 

                if (!HasModifiers) 
                {
                    Value = modifiedValue.BaseValue;
                }
                else 
                {
                    ComputeIsDeferred(); 
                } 
            }
        } 

        // remove all modifiers, retain value source, and set value to supplied value
        internal void ResetValue(object value, bool hasExpressionMarker)
        { 
            _source &= FullValueSource.ValueSourceMask;
            _value = value; 
            if (hasExpressionMarker) 
            {
                HasExpressionMarker = true; 
            }
            else
            {
                ComputeIsDeferred(); 
            }
            Debug.Assert(hasExpressionMarker == (value == DependencyObject.ExpressionInAlternativeStore), "hasExpressionMarker flag must match value"); 
        } 

        // add an expression marker back as the base value for an expression value 
        internal void RestoreExpressionMarker()
        {
            if (HasModifiers)
            { 
                ModifiedValue entry = ModifiedValue;
                entry.ExpressionValue = entry.BaseValue; 
                entry.BaseValue = DependencyObject.ExpressionInAlternativeStore; 
                _source |= FullValueSource.IsExpression | FullValueSource.HasExpressionMarker;
 
                //recompute the isDeferredReference flag as it may have changed
                ComputeIsDeferred();
            }
            else 
            {
                object value = Value; 
                Value = DependencyObject.ExpressionInAlternativeStore; 
                SetExpressionValue(value, DependencyObject.ExpressionInAlternativeStore);
                _source |= FullValueSource.HasExpressionMarker; 
            }


        } 

        // Computes and set the IsDeferred hint flag. 
        // This take into account all flags and should only be used sparingly. 
        private void ComputeIsDeferred()
        { 
            bool isDeferredReference = false;
            if (!HasModifiers)
            {
                isDeferredReference = Value is DeferredReference; 
            }
            else if (ModifiedValue != null) 
            { 
                if (IsCoercedWithCurrentValue)
                { 
                    isDeferredReference = ModifiedValue.CoercedValue is DeferredReference;
                }
                else if (IsExpression)
                { 
                    isDeferredReference = ModifiedValue.ExpressionValue is DeferredReference;
                } 
 
                // For animated values isDeferred will always be false.
            } 

            IsDeferredReference = isDeferredReference;
        }
 

        #endregion InternalMethods 
 
        #region InternalProperties
 
        public int PropertyIndex
        {
            get { return _propertyIndex; }
            set { _propertyIndex = (short)value; } 
        }
 
        ///  
        ///     If HasModifiers is true then it holds the value
        ///     else it holds the modified value instance 
        /// 
        internal object Value
        {
            get { return _value; } 
            set {
                _value = value; 
                IsDeferredReference = value is DeferredReference; 
                Debug.Assert(value is DeferredReference == IsDeferredReference);
            } 
        }

        internal BaseValueSourceInternal BaseValueSourceInternal
        { 
            get { return (BaseValueSourceInternal)(_source & FullValueSource.ValueSourceMask); }
            set { _source = (_source & ~FullValueSource.ValueSourceMask) | (FullValueSource)value; } 
        } 

        internal bool IsDeferredReference 
        {
            get
            {
                // When this flag is true we treat it as a hint rather than a guarantee and update 
                // it if is out of [....]. When the flag is false, however we expect it to guarantee
                // that the value isn't a DeferredReference. 
 
                bool isDeferredReference = ReadPrivateFlag(FullValueSource.IsPotentiallyADeferredReference);
                if (isDeferredReference) 
                {
                    // Check if the value is really a deferred reference
                    ComputeIsDeferred();
                    isDeferredReference = ReadPrivateFlag(FullValueSource.IsPotentiallyADeferredReference); 
                }
 
                return isDeferredReference; 
            }
 
            private set { WritePrivateFlag(FullValueSource.IsPotentiallyADeferredReference, value); }
        }

        internal bool IsExpression 
        {
            get { return ReadPrivateFlag(FullValueSource.IsExpression); } 
            private set { WritePrivateFlag(FullValueSource.IsExpression, value); } 
        }
 
        internal bool IsAnimated
        {
            get { return ReadPrivateFlag(FullValueSource.IsAnimated); }
            private set { WritePrivateFlag(FullValueSource.IsAnimated, value); } 
        }
 
        internal bool IsCoerced 
        {
            get { return ReadPrivateFlag(FullValueSource.IsCoerced); } 
            private set { WritePrivateFlag(FullValueSource.IsCoerced, value); }
        }

        internal bool HasModifiers 
        {
            get { return (_source & FullValueSource.ModifiersMask) != 0; } 
        } 

        internal FullValueSource FullValueSource 
        {
            get { return _source; }
        }
 

        internal bool HasExpressionMarker 
        { 
            get { return ReadPrivateFlag(FullValueSource.HasExpressionMarker); }
            set { WritePrivateFlag(FullValueSource.HasExpressionMarker, value); } 
        }

        internal bool IsCoercedWithCurrentValue
        { 
            get { return ReadPrivateFlag(FullValueSource.IsCoercedWithCurrentValue); }
            set { WritePrivateFlag(FullValueSource.IsCoercedWithCurrentValue, value); } 
        } 

        internal EffectiveValueEntry GetFlattenedEntry(RequestFlags requests) 
        {
            if ((_source & (FullValueSource.ModifiersMask | FullValueSource.HasExpressionMarker)) == 0)
            {
                // If the property does not have any modifiers 
                // then just return the base value.
                return this; 
            } 

            if (!HasModifiers) 
            {
                Debug.Assert(HasExpressionMarker);

                // This is the case when some one stuck an expression into 
                // an alternate store such as a style or a template but the
                // new value for the expression has not been evaluated yet. 
                // In the intermediate we need to return the default value 
                // for the property. This problem was manifested in DRTDocumentViewer.
                EffectiveValueEntry unsetEntry = new EffectiveValueEntry(); 
                unsetEntry.BaseValueSourceInternal = BaseValueSourceInternal;
                unsetEntry.PropertyIndex = PropertyIndex;
                return unsetEntry;
            } 

            // else entry has modifiers 
            EffectiveValueEntry entry = new EffectiveValueEntry(); 
            entry.BaseValueSourceInternal = BaseValueSourceInternal;
            entry.PropertyIndex = PropertyIndex; 
            entry.IsDeferredReference = IsDeferredReference;

            // If the property has a modifier return the modified value
            Debug.Assert(ModifiedValue != null); 

            // outside of DO, we flatten modified value 
            ModifiedValue modifiedValue = ModifiedValue; 

            // Note that the modified values have an order of precedence 
            // 1. Coerced Value (including Current value)
            // 2. Animated Value
            // 3. Expression Value
            // Also note that we support any arbitrary combinations of these 
            // modifiers and will yet the precedence metioned above.
            if (IsCoerced) 
            { 
                if ((requests & RequestFlags.CoercionBaseValue) == 0)
                { 
                    entry.Value = modifiedValue.CoercedValue;
                }
                else
                { 
                    // This is the case when CoerceValue tries to query
                    // the old base value for the property 
                    if (IsCoercedWithCurrentValue) 
                    {
                        entry.Value = modifiedValue.CoercedValue; 
                    }
                    else if (IsAnimated && ((requests & RequestFlags.AnimationBaseValue) == 0))
                    {
                        entry.Value = modifiedValue.AnimatedValue; 
                    }
                    else if (IsExpression) 
                    { 
                        entry.Value = modifiedValue.ExpressionValue;
                    } 
                    else
                    {
                        entry.Value = modifiedValue.BaseValue;
                    } 
                }
            } 
            else if (IsAnimated) 
            {
                if ((requests & RequestFlags.AnimationBaseValue) == 0) 
                {
                    entry.Value = modifiedValue.AnimatedValue;
                }
                else 
                {
                    // This is the case when [UI/Content]Element are 
                    // requesting the base value of an animation. 
                    if (IsExpression)
                    { 
                        entry.Value = modifiedValue.ExpressionValue;
                    }
                    else
                    { 
                        entry.Value = modifiedValue.BaseValue;
                     } 
                } 
            }
            else 
            {
                Debug.Assert(IsExpression == true);

                object expressionValue = modifiedValue.ExpressionValue; 

                entry.Value = expressionValue; 
            } 

            Debug.Assert(entry.IsDeferredReference == (entry.Value is DeferredReference), "Value and DeferredReference flag should be in [....]; hitting this may mean that it's time to divide the DeferredReference flag into a set of flags, one for each modifier"); 

            return entry;
        }
 
        internal void SetAnimationBaseValue(object animationBaseValue)
        { 
            if (!HasModifiers) 
            {
                Value = animationBaseValue; 
            }
            else
            {
                ModifiedValue modifiedValue = ModifiedValue; 

                if (IsExpression) 
                { 
                    modifiedValue.ExpressionValue = animationBaseValue;
                } 
                else
                {
                    modifiedValue.BaseValue = animationBaseValue;
                } 

                //the modified value may be a deferred reference so recompute this flag. 
                ComputeIsDeferred(); 
            }
        } 

        internal void SetCoersionBaseValue(object coersionBaseValue)
        {
            if (!HasModifiers) 
            {
                Value = coersionBaseValue; 
            } 
            else
            { 
                ModifiedValue modifiedValue = ModifiedValue;

                if (IsAnimated)
                { 
                    modifiedValue.AnimatedValue = coersionBaseValue;
                } 
                else if (IsExpression) 
                {
                    modifiedValue.ExpressionValue = coersionBaseValue; 
                }
                else
                {
                    modifiedValue.BaseValue = coersionBaseValue; 
                }
                //the modified value may be a deferred reference so recompute this flag. 
                ComputeIsDeferred(); 
            }
        } 

        internal object LocalValue
        {
            get 
            {
                if (BaseValueSourceInternal == BaseValueSourceInternal.Local) 
                { 
                    if (!HasModifiers)
                    { 
                        Debug.Assert(Value != DependencyProperty.UnsetValue);
                        return Value;
                    }
                    else 
                    {
                        Debug.Assert(ModifiedValue != null && ModifiedValue.BaseValue != DependencyProperty.UnsetValue); 
                        return ModifiedValue.BaseValue; 
                    }
                } 
                else
                {
                    return DependencyProperty.UnsetValue;
                } 
            }
 
            set 
            {
                Debug.Assert(BaseValueSourceInternal == BaseValueSourceInternal.Local, "This can happen only on an entry already having a local value"); 

                if (!HasModifiers)
                {
                    Debug.Assert(Value != DependencyProperty.UnsetValue); 
                    Value = value;
                } 
                else 
                {
                    Debug.Assert(ModifiedValue != null && ModifiedValue.BaseValue != DependencyProperty.UnsetValue); 
                    ModifiedValue.BaseValue = value;
                }
            }
        } 

        internal ModifiedValue ModifiedValue 
        { 
            get
            { 
                if (_value != null)
                {
                    return _value as ModifiedValue;
                } 
                return null;
            } 
        } 

        private ModifiedValue EnsureModifiedValue() 
        {
            ModifiedValue modifiedValue = null;
            if (_value == null)
            { 
                _value = modifiedValue = new ModifiedValue();
            } 
            else 
            {
                modifiedValue = _value as ModifiedValue; 
                if (modifiedValue == null)
                {
                    modifiedValue = new ModifiedValue();
                    modifiedValue.BaseValue = _value; 
                    _value = modifiedValue;
                } 
            } 
            return modifiedValue;
        } 

        internal void Clear()
        {
            _propertyIndex = -1; 
            _value = null;
            _source = 0; 
        } 

        #endregion InternalProperties 

        #region PrivateMethods

        private void WritePrivateFlag(FullValueSource bit, bool value) 
        {
            if (value) 
            { 
                _source |= bit;
            } 
            else
            {
                _source &= ~bit;
            } 
        }
 
        private bool ReadPrivateFlag(FullValueSource bit) 
        {
            return (_source & bit) != 0; 
        }

        #endregion PrivateMethods
 
        #region Data
 
        private object                      _value; 
        private short                       _propertyIndex;
        private FullValueSource             _source; 

        #endregion Data
    }
 

    [FriendAccessAllowed] // Built into Base, also used by Core & Framework. 
    internal enum FullValueSource : short 
    {
        // Bit used to store BaseValueSourceInternal = 0x01 
        // Bit used to store BaseValueSourceInternal = 0x02
        // Bit used to store BaseValueSourceInternal = 0x04
        // Bit used to store BaseValueSourceInternal = 0x08
 
        ValueSourceMask     = 0x000F,
        ModifiersMask       = 0x0070, 
        IsExpression        = 0x0010, 
        IsAnimated          = 0x0020,
        IsCoerced           = 0x0040, 
        IsPotentiallyADeferredReference = 0x0080,
        HasExpressionMarker = 0x0100,
        IsCoercedWithCurrentValue = 0x200,
    } 

    // Note that these enum values are arranged in the reverse order of 
    // precendence for these sources. Local value has highest 
    // precedence and Default value has the least. Note that we do not
    // store default values in the _effectiveValues cache unless it is 
    // being coerced/animated.
    [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    internal enum BaseValueSourceInternal : short
    { 
        Unknown                 = 0,
        Default                 = 1, 
        Inherited               = 2, 
        ThemeStyle              = 3,
        ThemeStyleTrigger       = 4, 
        Style                   = 5,
        TemplateTrigger         = 6,
        StyleTrigger            = 7,
        ImplicitReference       = 8, 
        ParentTemplate          = 9,
        ParentTemplateTrigger   = 10, 
        Local                   = 11, 
    }
 
    [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    internal class ModifiedValue
    {
        #region InternalProperties 

        internal object BaseValue 
        { 
            get { return _baseValue; }
            set { _baseValue = value; } 
        }

        internal object ExpressionValue
        { 
            get { return _expressionValue; }
            set { _expressionValue = value; } 
        } 

        internal object AnimatedValue 
        {
            get { return _animatedValue; }
            set { _animatedValue = value; }
        } 

        internal object CoercedValue 
        { 
            get { return _coercedValue; }
            set { _coercedValue = value; } 
        }

        #endregion InternalProperties
 
        #region Data
 
        private object _baseValue; 
        private object _expressionValue;
        private object _animatedValue; 
        private object _coercedValue;

        #endregion Data
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK