• WPF依赖对象(DependencyObject) 实现源码,理解WPF原理必读


    /// DependencyObject encompasses all property engine services. It's primary function
    /// is providing facilities to compute a property's value based on other properties.<para/>
    ///
    /// The Property Engine introduces a new type of property: attached properties. Attached
    /// properties are identified via <see cref="DependencyProperty"/> and are read and
    /// written using GetValue and SetValue.<para/>
    ///
    /// Attached properties may be set and queried on any DependencyObject-derived type.<para/>
    ///
    /// <see cref="Expression"/> is used to define relationships between properties. SetValue
    /// is used to apply the Expression to the property on the instance.

       1 // #define NESTED_OPERATIONS_
       2  
       3 using System;
       4 using System.Collections;
       5 using System.Diagnostics;
       6 using System.Globalization; // For CultureInfo.InvariantCulture
       7 using System.Reflection;
       8 using System.Security.Permissions; // For LinkDemand
       9  
      10 using System.Windows.Threading;
      11  
      12 using MS.Utility;
      13 using MS.Internal;
      14 using MS.Internal.WindowsBase;
      15 using System.Windows.Markup;
      16  
      17 namespace System.Windows
      18 {
      19     /// <summary>
      20     ///     DependencyObject is an object that participates in the property dependency system
      21     /// </summary>
      22     /// <remarks>
      23   
      24     ///
      25     ///     DependencyObject services include the following:
      26     ///     <para/>
      27     ///     <list type="bullet">
      28     ///         <item>Dependency-based property value evaluation through Expressions</item>
      29     ///         <item>Property invalidation dependent traversal through Expressions</item>
      30     ///         <item>Attached property support</item>
      31     ///         <item>Invalidation notification services</item>
      32     ///     </list>
      33     /// </remarks>
      34     /// This attribute allows designers looking at metadata through TypeDescriptor to see dependency properties
      35     /// and attached properties.
      36     [System.ComponentModel.TypeDescriptionProvider(typeof(MS.Internal.ComponentModel.DependencyObjectProvider))]
      37     [System.Windows.Markup.NameScopeProperty("NameScope", typeof(System.Windows.NameScope))]
      38     public class DependencyObject : DispatcherObject
      39     {
      40         /// <summary>
      41         ///     Default DependencyObject constructor
      42         /// </summary>
      43         /// <remarks>
      44         ///     Automatic determination of current Dispatcher. Use alternative constructor
      45         ///     that accepts a Dispatcher for best performance.
      46         /// </remarks>
      47         public DependencyObject()
      48         {
      49             Initialize();
      50         }
      51  
      52         /// <summary>Returns the DType that represents the CLR type of this instance</summary>
      53         public DependencyObjectType DependencyObjectType
      54         {
      55             get
      56             {
      57                 if (_dType == null)
      58                 {
      59                     // Specialized type identification
      60                     _dType = DependencyObjectType.FromSystemTypeInternal(GetType());
      61                 }
      62  
      63                 // Do not call VerifyAccess because this method is trivial.
      64                 return _dType;
      65             }
      66         }
      67  
      68         private void Initialize()
      69         {
      70             CanBeInheritanceContext = true;
      71             CanModifyEffectiveValues = true;
      72         }
      73  
      74         /// <summary>
      75         ///     Makes this object Read-Only state of this object; when in a Read-Only state, SetValue is not permitted,
      76         ///     though the effective value for a property may change.
      77         /// </summary>
      78         [FriendAccessAllowed] // Built into Base, also used by Framework.
      79         internal virtual void Seal()
      80         {
      81             Debug.Assert(!(this is Freezable), "A Freezable should not call DO's implementation of Seal()");
      82  
      83             // Currently DependencyObject.Seal() is semantically different than Freezable.Freeze().
      84             // Though freezing implies sealing the reverse isn't true.  The salient difference
      85             // here is that sealing a DependencyObject does not force all DPs on that object to
      86             // also be sealed.  Thus, when we Seal(), we promote all cached values to locally set
      87             // so that the user can continue to modify them.  Freezable types instead strip off
      88             // the promotion handler and freeze the cached default. Note that when / if we make
      89             // Seal() == Freeze this code should go away in favor of the behavior used for Freezables.
      90             PropertyMetadata.PromoteAllCachedDefaultValues(this);
      91  
      92             // Since Freeze doesn't call Seal the code below will also be duplicated in Freeze().
      93  
      94             // Since this object no longer changes it won't be able to notify dependents
      95             DependentListMapField.ClearValue(this);
      96  
      97             DO_Sealed = true;
      98         }
      99  
     100         /// <summary>
     101         ///     Indicates whether or not this object is in a Read-Only state; when in a Read-Only state, SetValue is not permitted,
     102         ///     though the effective value for a property may change.
     103         /// </summary>
     104         public bool IsSealed
     105         {
     106             get
     107             {
     108                 return DO_Sealed;
     109             }
     110         }
     111  
     112         /// <summary>
     113         ///     We override Equals() to seal it to prevent custom Equals()
     114         ///     implementations.
     115         ///
     116         ///     There are only two scenarios where overriding Equals makes
     117         ///     sense:
     118         ///
     119         ///         1.  You are a value type (passed by copy).
     120         ///         2.  You are an immutable reference type (e.g., System.String).
     121         ///
     122         ///     Otherwise you are going to cause problems with keyed and
     123         ///     some types of sorted datastructures because your values
     124         ///     can mutate to be equals or not equals while they reside in
     125         ///     the store (bad news for System.Collections(.Generic)).
     126         ///
     127         ///     Furthermore, defining equality for two DOs is a very slippery
     128         ///     slope.  Are two brushes "equal" if they both paint red?  What
     129         ///     if one is only red this frame because it is animated?  What if
     130         ///     one is databound?  What if one is frozen?  ...and so on.
     131         ///
     132         ///     Since a DO can never be immutable (attached properties, etc.)
     133         ///     it makes sense to disallow overriding of Equals.
     134         /// </summary>
     135         public override sealed bool Equals(Object obj)
     136         {
     137             return base.Equals(obj);
     138         }
     139  
     140         /// <summary>
     141         ///     CS0659: Required when overriding Equals().  Overriding
     142         ///     GetHashCode() is a bad idea for similar reasons.
     143         /// </summary>
     144         public override sealed int GetHashCode()
     145         {
     146             return base.GetHashCode();
     147         }
     148  
     149         /// <summary>
     150         ///     Retrieve the value of a property
     151         /// </summary>
     152         /// <param name="dp">Dependency property</param>
     153         /// <returns>The computed value</returns>
     154         public object GetValue(DependencyProperty dp)
     155         {
     156             // Do not allow foreign threads access.
     157             // (This is a noop if this object is not assigned to a Dispatcher.)
     158             //
     159             this.VerifyAccess();
     160  
     161             if (dp == null)
     162             {
     163                 throw new ArgumentNullException("dp");
     164             }
     165  
     166             // Call Forwarded
     167             return GetValueEntry(
     168                     LookupEntry(dp.GlobalIndex),
     169                     dp,
     170                     null,
     171                     RequestFlags.FullyResolved).Value;
     172         }
     173  
     174         /// <summary>
     175         ///     This overload of GetValue returns UnsetValue if the property doesn't
     176         ///     have an entry in the _effectiveValues. This way we will avoid inheriting
     177         ///     the default value from the parent.
     178         /// </summary>
     179         [FriendAccessAllowed] // Built into Base, also used by Core.
     180         internal EffectiveValueEntry GetValueEntry(
     181             EntryIndex          entryIndex,
     182             DependencyProperty  dp,
     183             PropertyMetadata    metadata,
     184             RequestFlags        requests)
     185         {
     186             EffectiveValueEntry entry;
     187  
     188             if (dp.ReadOnly)
     189             {
     190                 if (metadata == null)
     191                 {
     192                     metadata = dp.GetMetadata(DependencyObjectType);
     193                 }
     194  
     195                 GetReadOnlyValueCallback getValueCallback = metadata.GetReadOnlyValueCallback;
     196                 if (getValueCallback != null)
     197                 {
     198                     BaseValueSourceInternal valueSource;
     199                     entry = new EffectiveValueEntry(dp);
     200                     entry.Value = getValueCallback(this, out valueSource);
     201                     entry.BaseValueSourceInternal = valueSource;
     202                     return entry;
     203                 }
     204             }
     205  
     206             if (entryIndex.Found)
     207             {
     208                 if ((requests & RequestFlags.RawEntry) != 0)
     209                 {
     210                     entry = _effectiveValues[entryIndex.Index];
     211                 }
     212                 else
     213                 {
     214                     entry = GetEffectiveValue(
     215                                 entryIndex,
     216                                 dp,
     217                                 requests);
     218                 }
     219             }
     220             else
     221             {
     222                 entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Unknown);
     223             }
     224  
     225             if (entry.Value == DependencyProperty.UnsetValue)
     226             {
     227                 if (dp.IsPotentiallyInherited)
     228                 {
     229                     if (metadata == null)
     230                     {
     231                         metadata = dp.GetMetadata(DependencyObjectType);
     232                     }
     233  
     234                     if (metadata.IsInherited)
     235                     {
     236                         DependencyObject inheritanceParent = InheritanceParent;
     237                         if (inheritanceParent != null)
     238                         {
     239                             entryIndex = inheritanceParent.LookupEntry(dp.GlobalIndex);
     240  
     241                             if (entryIndex.Found)
     242                             {
     243                                 entry = inheritanceParent.GetEffectiveValue(
     244                                                 entryIndex,
     245                                                 dp,
     246                                                 requests & RequestFlags.DeferredReferences);
     247                                 entry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited;
     248                             }
     249                         }
     250                     }
     251  
     252                     if (entry.Value != DependencyProperty.UnsetValue)
     253                     {
     254                         return entry;
     255                     }
     256                 }
     257  
     258                 if ((requests & RequestFlags.SkipDefault) == 0)
     259                 {
     260                     if (dp.IsPotentiallyUsingDefaultValueFactory)
     261                     {
     262                         if (metadata == null)
     263                         {
     264                             metadata = dp.GetMetadata(DependencyObjectType);
     265                         }
     266  
     267                         if (((requests & (RequestFlags.DeferredReferences | RequestFlags.RawEntry)) != 0) && metadata.UsingDefaultValueFactory)
     268                         {
     269                             entry.BaseValueSourceInternal = BaseValueSourceInternal.Default;
     270  
     271                             entry.Value = new DeferredMutableDefaultReference(metadata, this, dp);
     272                             return entry;
     273                         }
     274                     }
     275                     else if (!dp.IsDefaultValueChanged)
     276                     {
     277                         return EffectiveValueEntry.CreateDefaultValueEntry(dp, dp.DefaultMetadata.DefaultValue);
     278                     }
     279  
     280                     if (metadata == null)
     281                     {
     282                         metadata = dp.GetMetadata(DependencyObjectType);
     283                     }
     284  
     285                     return EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
     286                 }
     287             }
     288             return entry;
     289         }
     290  
     291         /// <summary>
     292         ///     This overload of GetValue assumes that entryIndex is valid.
     293         ///      It also does not do the check storage on the InheritanceParent.
     294         /// </summary>
     295         private EffectiveValueEntry GetEffectiveValue(
     296             EntryIndex          entryIndex,
     297             DependencyProperty  dp,
     298             RequestFlags        requests)
     299         {
     300             EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
     301             EffectiveValueEntry effectiveEntry = entry.GetFlattenedEntry(requests);
     302  
     303             if (((requests & (RequestFlags.DeferredReferences | RequestFlags.RawEntry)) != 0) || !effectiveEntry.IsDeferredReference)
     304             {
     305                 return effectiveEntry;
     306             }
     307  
     308             if (!entry.HasModifiers)
     309             {
     310                 // For thread-safety, sealed DOs can't modify _effectiveValues.
     311                 Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
     312  
     313                 if (!entry.HasExpressionMarker)
     314                 {
     315                     // The value for this property was meant to come from a dictionary
     316                     // and the creation of that value had been deferred until this
     317                     // time for better performance. Now is the time to actually instantiate
     318                     // this value by querying it from the dictionary. Once we have the
     319                     // value we can actually replace the deferred reference marker
     320                     // with the actual value.
     321                     DeferredReference reference = (DeferredReference)entry.Value;
     322                     object value = reference.GetValue(entry.BaseValueSourceInternal);
     323  
     324                     if (!dp.IsValidValue(value))
     325                     {
     326                         throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
     327                     }
     328  
     329                     // Make sure the entryIndex is in sync after
     330                     // the inflation of the deferred reference.
     331                     entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     332  
     333                     entry.Value = value;
     334  
     335                     _effectiveValues[entryIndex.Index] = entry;
     336                     return entry;
     337                 }
     338             }
     339             else
     340             {
     341                 // The value for this property was meant to come from a dictionary
     342                 // and the creation of that value had been deferred until this
     343                 // time for better performance. Now is the time to actually instantiate
     344                 // this value by querying it from the dictionary. Once we have the
     345                 // value we can actually replace the deferred reference marker
     346                 // with the actual value.
     347  
     348                 ModifiedValue modifiedValue = entry.ModifiedValue;
     349                 DeferredReference reference = null;
     350                 bool referenceFromExpression = false;
     351  
     352                 if (entry.IsCoercedWithCurrentValue)
     353                 {
     354                     if (!entry.IsAnimated)
     355                     {
     356                         reference = modifiedValue.CoercedValue as DeferredReference;
     357                     }
     358                 }
     359  
     360                 if (reference == null && entry.IsExpression)
     361                 {
     362                     if (!entry.IsAnimated && !entry.IsCoerced)
     363                     {
     364                         reference = (DeferredReference) modifiedValue.ExpressionValue;
     365                         referenceFromExpression = true;
     366                     }
     367                 }
     368  
     369                 Debug.Assert(reference != null, "the only modified values that can have deferredreferences are (a) expression, (b) coerced control value");
     370                 if (reference == null)
     371                 {
     372                     return effectiveEntry;
     373                 }
     374  
     375                 object value = reference.GetValue(entry.BaseValueSourceInternal);
     376  
     377                 if (!dp.IsValidValue(value))
     378                 {
     379                     throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
     380                 }
     381  
     382                 // Make sure the entryIndex is in sync after
     383                 // the inflation of the deferred reference.
     384                 entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     385  
     386                 if (referenceFromExpression)
     387                 {
     388                     entry.SetExpressionValue(value, modifiedValue.BaseValue);
     389                 }
     390                 else
     391                 {
     392                     entry.SetCoercedValue(value, null, true /* skipBaseValueChecks */, entry.IsCoercedWithCurrentValue);
     393                 }
     394  
     395                 _effectiveValues[entryIndex.Index] = entry;
     396  
     397                 effectiveEntry.Value = value;
     398             }
     399             return effectiveEntry;
     400         }
     401  
     402         /// <summary>
     403         ///     Sets the local value of a property
     404         /// </summary>
     405         /// <param name="dp">Dependency property</param>
     406         /// <param name="value">New local value</param>
     407         public void SetValue(DependencyProperty dp, object value)
     408         {
     409             // Do not allow foreign threads access.
     410             // (This is a noop if this object is not assigned to a Dispatcher.)
     411             //
     412             this.VerifyAccess();
     413  
     414             // Cache the metadata object this method needed to get anyway.
     415             PropertyMetadata metadata = SetupPropertyChange(dp);
     416  
     417             // Do standard property set
     418             SetValueCommon(dp, value, metadata, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown, false /* isInternal */);
     419         }
     420  
     421         /// <summary>
     422         ///     Sets the value of a property without changing its value source.
     423         /// </summary>
     424         /// <param name="dp">Dependency property</param>
     425         /// <param name="value">New value</param>
     426         /// <remarks>
     427         ///     This method is intended for use by a component that wants to
     428         ///     programmatically set the value of one of its own properties, in a
     429         ///     way that does not disable an application's declared use of that property.
     430         ///     SetCurrentValue changes the effective value of the property, but
     431         ///     existing triggers, data-binding, styles, etc. will continue to
     432         ///     work.
     433         /// </remarks>
     434         public void SetCurrentValue(DependencyProperty dp, object value)
     435         {
     436             // Do not allow foreign threads access.
     437             // (This is a noop if this object is not assigned to a Dispatcher.)
     438             this.VerifyAccess();
     439  
     440             // Cache the metadata object this method needed to get anyway.
     441             PropertyMetadata metadata = SetupPropertyChange(dp);
     442  
     443             // Do standard property set
     444             SetValueCommon(dp, value, metadata, false /* coerceWithDeferredReference */, true /* coerceWithCurrentValue */, OperationType.Unknown, false /* isInternal */);
     445         }
     446  
     447         /// <summary>
     448         ///     Sets the local value of a property
     449         /// The purpose of this internal method is to reuse BooleanBoxes when setting boolean value
     450         /// </summary>
     451         /// <param name="dp">Dependency property</param>
     452         /// <param name="value">New local value</param>
     453         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
     454         internal void SetValue(DependencyProperty dp, bool value)
     455         {
     456             SetValue(dp, MS.Internal.KnownBoxes.BooleanBoxes.Box(value));
     457         }
     458  
     459         /// <summary>
     460         ///     Sets the current value of a property
     461         /// The purpose of this internal method is to reuse BooleanBoxes when setting boolean value
     462         /// </summary>
     463         /// <param name="dp">Dependency property</param>
     464         /// <param name="value">New local value</param>
     465         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
     466         internal void SetCurrentValue(DependencyProperty dp, bool value)
     467         {
     468             SetCurrentValue(dp, MS.Internal.KnownBoxes.BooleanBoxes.Box(value));
     469         }
     470  
     471         /// <summary>
     472         ///     Internal version of SetValue that bypasses type check in IsValidValue;
     473         ///     This is used in property setters
     474         /// </summary>
     475         /// <param name="dp">Dependency property</param>
     476         /// <param name="value">New local value</param>
     477         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
     478         internal void SetValueInternal(DependencyProperty dp, object value)
     479         {
     480             // Do not allow foreign threads access.
     481             // (This is a noop if this object is not assigned to a Dispatcher.)
     482             //
     483             this.VerifyAccess();
     484  
     485             // Cache the metadata object this method needed to get anyway.
     486             PropertyMetadata metadata = SetupPropertyChange(dp);
     487  
     488             // Do standard property set
     489             SetValueCommon(dp, value, metadata, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown, true /* isInternal */);
     490         }
     491  
     492         /// <summary>
     493         ///     Internal version of SetCurrentValue that bypasses type check in IsValidValue;
     494         ///     This is used in property setters
     495         /// </summary>
     496         /// <param name="dp">Dependency property</param>
     497         /// <param name="value">New local value</param>
     498         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
     499         internal void SetCurrentValueInternal(DependencyProperty dp, object value)
     500         {
     501             // Do not allow foreign threads access.
     502             // (This is a noop if this object is not assigned to a Dispatcher.)
     503             //
     504             this.VerifyAccess();
     505  
     506             // Cache the metadata object this method needed to get anyway.
     507             PropertyMetadata metadata = SetupPropertyChange(dp);
     508  
     509             // Do standard property set
     510             SetValueCommon(dp, value, metadata, false /* coerceWithDeferredReference */, true /* coerceWithCurrentValue */, OperationType.Unknown, true /* isInternal */);
     511         }
     512  
     513         /// <summary>
     514         /// Sets the local value of a property.
     515         /// </summary>
     516         [FriendAccessAllowed] // Built into Base, also used by Framework.
     517         internal void SetDeferredValue(DependencyProperty dp, DeferredReference deferredReference)
     518         {
     519             // Cache the metadata object this method needed to get anyway.
     520             PropertyMetadata metadata = SetupPropertyChange(dp);
     521  
     522             // Do standard property set
     523             SetValueCommon(dp, deferredReference, metadata, true /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown, false /* isInternal */);
     524         }
     525  
     526         /// <summary>
     527         /// Sets the value of a property to a deferred reference, without changing the ValueSource.
     528         /// </summary>
     529         [FriendAccessAllowed] // Built into Base, also used by Framework.
     530         internal void SetCurrentDeferredValue(DependencyProperty dp, DeferredReference deferredReference)
     531         {
     532             // Cache the metadata object this method needed to get anyway.
     533             PropertyMetadata metadata = SetupPropertyChange(dp);
     534  
     535             // Do standard property set
     536             SetValueCommon(dp, deferredReference, metadata, true /* coerceWithDeferredReference */, true /* coerceWithCurrentValue */, OperationType.Unknown, false /* isInternal */);
     537         }
     538  
     539         /// <summary>
     540         /// Sets the local value of a property with a mutable default value.
     541         /// </summary>
     542         [FriendAccessAllowed] // Built into Base, also used by Framework.
     543         internal void SetMutableDefaultValue(DependencyProperty dp, object value)
     544         {
     545             // Cache the metadata object this method needed to get anyway.
     546             PropertyMetadata metadata = SetupPropertyChange(dp);
     547  
     548             // Do standard property set
     549             SetValueCommon(dp, value, metadata, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.ChangeMutableDefaultValue, false /* isInternal */);
     550         }
     551  
     552         /// <summary>
     553         ///     Sets the local value of a property
     554         /// The purpose of this internal method is to reuse BooleanBoxes when setting boolean value
     555         /// </summary>
     556         /// <param name="dp">Dependency property key</param>
     557         /// <param name="value">New local value</param>
     558         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
     559         internal void SetValue(DependencyPropertyKey dp, bool value)
     560         {
     561             SetValue(dp, MS.Internal.KnownBoxes.BooleanBoxes.Box(value));
     562         }
     563  
     564         /// <summary>
     565         ///     Sets the local value of a property
     566         /// </summary>
     567         public void SetValue(DependencyPropertyKey key, object value)
     568         {
     569             // Do not allow foreign threads access.
     570             // (This is a noop if this object is not assigned to a Dispatcher.)
     571             //
     572             this.VerifyAccess();
     573  
     574             DependencyProperty dp;
     575  
     576             // Cache the metadata object this method needed to get anyway.
     577             PropertyMetadata metadata = SetupPropertyChange(key, out dp);
     578  
     579             // Do standard property set
     580             SetValueCommon(dp, value, metadata, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown, false /* isInternal */);
     581         }
     582  
     583         /// <summary>
     584         ///     Called by SetValue or ClearValue to verify that the property
     585         /// can be changed.
     586         /// </summary>
     587         private PropertyMetadata SetupPropertyChange(DependencyProperty dp)
     588         {
     589             if ( dp != null )
     590             {
     591                 if ( !dp.ReadOnly )
     592                 {
     593                     // Get type-specific metadata for this property
     594                     return dp.GetMetadata(DependencyObjectType);
     595                 }
     596                 else
     597                 {
     598                     throw new InvalidOperationException(SR.Get(SRID.ReadOnlyChangeNotAllowed, dp.Name));
     599                 }
     600             }
     601             else
     602             {
     603                 throw new ArgumentNullException("dp");
     604             }
     605         }
     606  
     607         /// <summary>
     608         ///     Called by SetValue or ClearValue to verify that the property
     609         /// can be changed.
     610         /// </summary>
     611         private PropertyMetadata SetupPropertyChange(DependencyPropertyKey key, out DependencyProperty dp)
     612         {
     613             if ( key != null )
     614             {
     615                 dp = key.DependencyProperty;
     616                 Debug.Assert(dp != null);
     617  
     618                 dp.VerifyReadOnlyKey(key);
     619  
     620                 // Get type-specific metadata for this property
     621                 return dp.GetMetadata(DependencyObjectType);
     622             }
     623             else
     624             {
     625                 throw new ArgumentNullException("key");
     626             }
     627         }
     628  
     629         /// <summary>
     630         ///     The common code shared by all variants of SetValue
     631         /// </summary>
     632         // Takes metadata from caller because most of them have already retrieved it
     633         //  for their own purposes, avoiding the duplicate GetMetadata call.
     634         private void SetValueCommon(
     635             DependencyProperty  dp,
     636             object              value,
     637             PropertyMetadata    metadata,
     638             bool                coerceWithDeferredReference,
     639             bool                coerceWithCurrentValue,
     640             OperationType       operationType,
     641             bool                isInternal)
     642         {
     643             if (IsSealed)
     644             {
     645                 throw new InvalidOperationException(SR.Get(SRID.SetOnReadOnlyObjectNotAllowed, this));
     646             }
     647  
     648             Expression newExpr = null;
     649             DependencySource[] newSources = null;
     650  
     651             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
     652  
     653             // Treat Unset as a Clear
     654             if( value == DependencyProperty.UnsetValue )
     655             {
     656                 Debug.Assert(!coerceWithCurrentValue, "Don't call SetCurrentValue with UnsetValue");
     657                 // Parameters should have already been validated, so we call
     658                 //  into the private method to avoid validating again.
     659                 ClearValueCommon(entryIndex, dp, metadata);
     660                 return;
     661             }
     662  
     663             // Validate the "value" against the DP.
     664             bool isDeferredReference = false;
     665             bool newValueHasExpressionMarker = (value == ExpressionInAlternativeStore);
     666  
     667             // First try to validate the value; only after this validation fails should we
     668             // do the more expensive checks (type checks) for the less common scenarios
     669             if (!newValueHasExpressionMarker)
     670             {
     671                 bool isValidValue = isInternal ? dp.IsValidValueInternal(value) : dp.IsValidValue(value);
     672  
     673                 // for properties of type "object", we have to always check for expression & deferredreference
     674                 if (!isValidValue || dp.IsObjectType)
     675                 {
     676                     // 2nd most common is expression
     677                     newExpr = value as Expression;
     678                     if (newExpr != null)
     679                     {
     680                         // For Expressions, perform additional validation
     681                         // Make sure Expression is "attachable"
     682                         if (!newExpr.Attachable)
     683                         {
     684                             throw new ArgumentException(SR.Get(SRID.SharingNonSharableExpression));
     685                         }
     686  
     687                         // Check dispatchers of all Sources
     688                         // CALLBACK
     689                         newSources = newExpr.GetSources();
     690                         ValidateSources(this, newSources, newExpr);
     691                     }
     692                     else
     693                     {
     694                         // and least common is DeferredReference
     695                         isDeferredReference = (value is DeferredReference);
     696                         if (!isDeferredReference)
     697                         {
     698                             if (!isValidValue)
     699                             {
     700                                 // it's not a valid value & it's not an expression, so throw
     701                                 throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
     702                             }
     703                         }
     704                     }
     705                 }
     706             }
     707  
     708             // Get old value
     709             EffectiveValueEntry oldEntry;
     710             if (operationType == OperationType.ChangeMutableDefaultValue)
     711             {
     712                 oldEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default);
     713                 oldEntry.Value = value;
     714             }
     715             else
     716             {
     717                 oldEntry = GetValueEntry(entryIndex, dp, metadata, RequestFlags.RawEntry);
     718             }
     719  
     720             // if there's an expression in some other store, fetch it now
     721             Expression currentExpr =
     722                     (oldEntry.HasExpressionMarker)  ? _getExpressionCore(this, dp, metadata)
     723                   : (oldEntry.IsExpression)         ? (oldEntry.LocalValue as Expression)
     724                   :                                   null;
     725  
     726             // Allow expression to store value if new value is
     727             // not an Expression, if applicable
     728  
     729             bool handled = false;
     730             if ((currentExpr != null) && (newExpr == null))
     731             {
     732                 // Resolve deferred references because we haven't modified
     733                 // the expression code to work with DeferredReference yet.
     734                 if (isDeferredReference)
     735                 {
     736                     value = ((DeferredReference) value).GetValue(BaseValueSourceInternal.Local);
     737                 }
     738  
     739                 // CALLBACK
     740                 handled = currentExpr.SetValue(this, dp, value);
     741                 entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     742             }
     743  
     744             // Create the new effective value entry
     745             EffectiveValueEntry newEntry;
     746             if (handled)
     747             {
     748                 // If expression handled set, then done
     749                 if (entryIndex.Found)
     750                 {
     751                     newEntry = _effectiveValues[entryIndex.Index];
     752                 }
     753                 else
     754                 {
     755                     // the expression.SetValue resulted in this value being removed from the table;
     756                     // use the default value.
     757                     newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
     758                 }
     759  
     760                 coerceWithCurrentValue = false; // expression already handled the control-value
     761             }
     762             else
     763             {
     764                 // allow a control-value to coerce an expression value, when the
     765                 // expression didn't handle the value
     766                 if (coerceWithCurrentValue && currentExpr != null)
     767                 {
     768                     currentExpr = null;
     769                 }
     770  
     771                 newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);
     772  
     773                 // detach the old expression, if applicable
     774                 if (currentExpr != null)
     775                 {
     776                     // CALLBACK
     777                     DependencySource[] currentSources = currentExpr.GetSources();
     778  
     779                     UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false);  // Remove
     780  
     781                     // CALLBACK
     782                     currentExpr.OnDetach(this, dp);
     783                     currentExpr.MarkDetached();
     784                     entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     785                 }
     786  
     787                 // attach the new expression, if applicable
     788                 if (newExpr == null)
     789                 {
     790                     // simple local value set
     791                     newEntry.HasExpressionMarker = newValueHasExpressionMarker;
     792                     newEntry.Value = value;
     793                 }
     794                 else
     795                 {
     796                     Debug.Assert(!coerceWithCurrentValue, "Expression values not supported in SetCurrentValue");
     797  
     798                     // First put the expression in the effectivevalueentry table for this object;
     799                     // this allows the expression to update the value accordingly in OnAttach
     800                     SetEffectiveValue(entryIndex, dp, dp.GlobalIndex, metadata, newExpr, BaseValueSourceInternal.Local);
     801  
     802                     // Before the expression is attached it has default value
     803                     object defaultValue = metadata.GetDefaultValue(this, dp);
     804                     entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     805                     SetExpressionValue(entryIndex, defaultValue, newExpr);
     806                     UpdateSourceDependentLists(this, dp, newSources, newExpr, true);  // Add
     807  
     808                     newExpr.MarkAttached();
     809  
     810                     // CALLBACK
     811                     newExpr.OnAttach(this, dp);
     812  
     813                     // the attach may have added entries in the effective value table ...
     814                     // so, update the entryIndex accordingly.
     815                     entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     816  
     817                     newEntry = EvaluateExpression(
     818                             entryIndex,
     819                             dp,
     820                             newExpr,
     821                             metadata,
     822                             oldEntry,
     823                             _effectiveValues[entryIndex.Index]);
     824  
     825                     entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
     826                 }
     827             }
     828  
     829             UpdateEffectiveValue(
     830                 entryIndex,
     831                 dp,
     832                 metadata,
     833                 oldEntry,
     834                 ref newEntry,
     835                 coerceWithDeferredReference,
     836                 coerceWithCurrentValue,
     837                 operationType);
     838         }
     839  
     840         //
     841         //  This is a helper routine to set this DO as the inheritance context of another,
     842         //  which has been set as a DP value here.
     843         //
     844         [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
     845         internal bool ProvideSelfAsInheritanceContext( object value, DependencyProperty dp )
     846         {
     847             DependencyObject doValue = value as DependencyObject;
     848             if (doValue != null)
     849             {
     850                 return ProvideSelfAsInheritanceContext(doValue, dp);
     851             }
     852             else
     853             {
     854                 return false;
     855             }
     856         }
     857  
     858         [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
     859         internal bool ProvideSelfAsInheritanceContext( DependencyObject doValue, DependencyProperty dp )
     860         {
     861             // We have to call Freezable.AddInheritanceContext even if the request
     862             // for a new InheritanceContext is not allowed, because Freezable depends
     863             // on side-effects from setting the "Freezable context".  Freezable's
     864             // implementation does its own checks of the conditions omitted here.
     865             // 
     866  
     867  
     868             if (doValue != null &&
     869                 this.ShouldProvideInheritanceContext(doValue, dp) &&
     870                 (doValue is Freezable ||
     871                     (this.CanBeInheritanceContext &&
     872                      !doValue.IsInheritanceContextSealed)
     873                 ))
     874             {
     875                 DependencyObject oldInheritanceContext = doValue.InheritanceContext;
     876                 doValue.AddInheritanceContext(this, dp);
     877  
     878                 // return true if the inheritance context actually changed to the new value
     879                 return (this == doValue.InheritanceContext && this != oldInheritanceContext);
     880             }
     881             else
     882             {
     883                 return false;
     884             }
     885         }
     886  
     887         //
     888         //  This is a helper routine to remove this DO as the inheritance context of another.
     889         //
     890         [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
     891         internal bool RemoveSelfAsInheritanceContext( object value, DependencyProperty dp )
     892         {
     893             DependencyObject doValue = value as DependencyObject;
     894             if (doValue != null)
     895             {
     896                 return RemoveSelfAsInheritanceContext(doValue, dp);
     897             }
     898             else
     899             {
     900                 return false;
     901             }
     902         }
     903  
     904         [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
     905         internal bool RemoveSelfAsInheritanceContext( DependencyObject doValue, DependencyProperty dp )
     906         {
     907             // We have to call Freezable.RemoveInheritanceContext even if the request
     908             // for a new InheritanceContext is not allowed, because Freezable depends
     909             // on side-effects from setting the "Freezable context".  Freezable's
     910             // implementation does its own checks of the conditions omitted here.
     911             // 
     912  
     913  
     914             if (doValue != null &&
     915                 this.ShouldProvideInheritanceContext(doValue, dp) &&
     916                 (doValue is Freezable ||
     917                     (this.CanBeInheritanceContext &&
     918                      !doValue.IsInheritanceContextSealed)
     919                 ))
     920             {
     921                 DependencyObject oldInheritanceContext = doValue.InheritanceContext;
     922                 doValue.RemoveInheritanceContext(this, dp);
     923  
     924                 // return true if the inheritance context actually changed to the new value
     925                 return (this == oldInheritanceContext && doValue.InheritanceContext != oldInheritanceContext);
     926             }
     927             else
     928             {
     929                 return false;
     930             }
     931         }
     932  
     933  
     934         /// <summary>
     935         ///     Clears the local value of a property
     936         /// </summary>
     937         /// <param name="dp">Dependency property</param>
     938         public void ClearValue(DependencyProperty dp)
     939         {
     940             // Do not allow foreign threads to clear properties.
     941             // (This is a noop if this object is not assigned to a Dispatcher.)
     942             //
     943             this.VerifyAccess();
     944  
     945             // Cache the metadata object this method needed to get anyway.
     946             PropertyMetadata metadata = SetupPropertyChange(dp);
     947  
     948             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
     949  
     950             ClearValueCommon(entryIndex, dp, metadata);
     951         }
     952  
     953         /// <summary>
     954         ///     Clears the local value of a property
     955         /// </summary>
     956         public void ClearValue(DependencyPropertyKey key)
     957         {
     958             // Do not allow foreign threads to clear properties.
     959             // (This is a noop if this object is not assigned to a Dispatcher.)
     960             //
     961             this.VerifyAccess();
     962  
     963             DependencyProperty dp;
     964  
     965             // Cache the metadata object this method needed to get anyway.
     966             PropertyMetadata metadata = SetupPropertyChange(key, out dp);
     967  
     968             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
     969  
     970             ClearValueCommon(entryIndex, dp, metadata);
     971         }
     972  
     973         /// <summary>
     974         ///     The common code shared by all variants of ClearValue
     975         /// </summary>
     976         private void ClearValueCommon(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata)
     977         {
     978             if (IsSealed)
     979             {
     980                 throw new InvalidOperationException(SR.Get(SRID.ClearOnReadOnlyObjectNotAllowed, this));
     981             }
     982  
     983             // Get old value
     984             EffectiveValueEntry oldEntry = GetValueEntry(
     985                                         entryIndex,
     986                                         dp,
     987                                         metadata,
     988                                         RequestFlags.RawEntry);
     989  
     990             // Get current local value
     991             // (No need to go through read local callback, just checking
     992             // for presence of Expression)
     993             object current = oldEntry.LocalValue;
     994  
     995             // Get current expression
     996             Expression currentExpr = (oldEntry.IsExpression) ? (current as Expression) : null;
     997  
     998             // Inform value expression of detachment, if applicable
     999             if (currentExpr != null)
    1000             {
    1001                 // CALLBACK
    1002                 DependencySource[] currentSources = currentExpr.GetSources();
    1003  
    1004                 UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false);  // Remove
    1005  
    1006                 // CALLBACK
    1007                 currentExpr.OnDetach(this, dp);
    1008                 currentExpr.MarkDetached();
    1009                 entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
    1010             }
    1011  
    1012             // valuesource == Local && value == UnsetValue indicates that we are clearing the local value
    1013             EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);
    1014  
    1015             // Property is now invalid
    1016             UpdateEffectiveValue(
    1017                     entryIndex,
    1018                     dp,
    1019                     metadata,
    1020                     oldEntry,
    1021                     ref newEntry,
    1022                     false /* coerceWithDeferredReference */,
    1023                     false /* coerceWithCurrentValue */,
    1024                     OperationType.Unknown);
    1025         }
    1026  
    1027         /// <summary>
    1028         ///     This method is called by DependencyObjectPropertyDescriptor to determine
    1029         ///     if a value is set for a given DP.
    1030         /// </summary>
    1031         internal bool ContainsValue(DependencyProperty dp)
    1032         {
    1033             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
    1034  
    1035             if (!entryIndex.Found)
    1036             {
    1037                 return false;
    1038             }
    1039  
    1040             EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
    1041             object value = entry.IsCoercedWithCurrentValue ? entry.ModifiedValue.CoercedValue : entry.LocalValue;
    1042             return !object.ReferenceEquals(value, DependencyProperty.UnsetValue);
    1043         }
    1044  
    1045         //
    1046         // Changes the sources of an existing Expression
    1047         //
    1048         internal static void ChangeExpressionSources(Expression expr, DependencyObject d, DependencyProperty dp, DependencySource[] newSources)
    1049         {
    1050             if (!expr.ForwardsInvalidations)
    1051             {
    1052                 // Get current local value (should be provided Expression)
    1053                 // (No need to go through read local callback, just checking
    1054                 // for presence of Expression)
    1055                 EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex);
    1056  
    1057                 if (!entryIndex.Found || (d._effectiveValues[entryIndex.Index].LocalValue != expr))
    1058                 {
    1059                     throw new ArgumentException(SR.Get(SRID.SourceChangeExpressionMismatch));
    1060                 }
    1061             }
    1062  
    1063             // Get current sources
    1064             // CALLBACK
    1065             DependencySource[] currentSources = expr.GetSources();
    1066  
    1067             // Remove old
    1068             if (currentSources != null)
    1069             {
    1070                 UpdateSourceDependentLists(d, dp, currentSources, expr, false);  // Remove
    1071             }
    1072  
    1073             // Add new
    1074             if (newSources != null)
    1075             {
    1076                 UpdateSourceDependentLists(d, dp, newSources, expr, true);  // Add
    1077             }
    1078         }
    1079  
    1080         /// <summary>
    1081         ///     Coerce a property value
    1082         /// </summary>
    1083         /// <param name="dp">Dependency property</param>
    1084         public void CoerceValue(DependencyProperty dp)
    1085         {
    1086             // Do not allow foreign threads access.
    1087             // (This is a noop if this object is not assigned to a Dispatcher.)
    1088             //
    1089             this.VerifyAccess();
    1090  
    1091             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
    1092             PropertyMetadata metadata = dp.GetMetadata(DependencyObjectType);
    1093  
    1094             // if the property has a coerced-with-control value, apply the coercion
    1095             // to that value.  This is done by simply calling SetCurrentValue.
    1096             if (entryIndex.Found)
    1097             {
    1098                 EffectiveValueEntry entry = GetValueEntry(entryIndex, dp, metadata, RequestFlags.RawEntry);
    1099                 if (entry.IsCoercedWithCurrentValue)
    1100                 {
    1101                     SetCurrentValue(dp, entry.ModifiedValue.CoercedValue);
    1102                     return;
    1103                 }
    1104             }
    1105  
    1106             // IsCoerced == true && value == UnsetValue indicates that we need to re-coerce this value
    1107             EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced);
    1108  
    1109             UpdateEffectiveValue(
    1110                     entryIndex,
    1111                     dp,
    1112                     metadata,
    1113                     new EffectiveValueEntry() /* oldEntry */,
    1114                     ref newEntry,
    1115                     false /* coerceWithDeferredReference */,
    1116                     false /* coerceWithCurrentValue */,
    1117                     OperationType.Unknown);
    1118         }
    1119  
    1120         /// <summary>
    1121         ///     This is to enable some performance-motivated shortcuts in property
    1122         /// invalidation.  When this is called, it means the caller knows the
    1123         /// value of the property is pointing to the same object instance as
    1124         /// before, but the meaning has changed because something within that
    1125         /// object has changed.
    1126         /// </summary>
    1127         /// <remarks>
    1128         /// Clients who are unaware of this will still behave correctly, if not
    1129         ///  particularly performant, by assuming that we have a new instance.
    1130         /// Since invalidation operations are synchronous, we can set a bit
    1131         ///  to maintain this knowledge through the invalidation operation.
    1132         /// This would be problematic in cross-thread operations, but the only
    1133         ///  time DependencyObject can be used across thread in today's design
    1134         ///  is when it is a Freezable object that has been Frozen.  Frozen
    1135         ///  means no more changes, which means no more invalidations.
    1136         ///
    1137         /// This is being done as an internal method to enable the performance
    1138         ///  bug #1114409.  This is candidate for a public API but we can't
    1139         ///  do that kind of work at the moment.
    1140         /// </remarks>
    1141         [FriendAccessAllowed] // Built into Base, also used by Framework.
    1142         internal void InvalidateSubProperty(DependencyProperty dp)
    1143         {
    1144             // when a sub property changes, send a Changed notification with old and new value being the same, and with
    1145             // IsASubPropertyChange set to true
    1146             NotifyPropertyChange(new DependencyPropertyChangedEventArgs(dp, dp.GetMetadata(DependencyObjectType), GetValue(dp)));
    1147         }
    1148  
    1149         /// <summary>
    1150         ///     Notify the current DependencyObject that a "sub-property"
    1151         /// change has occurred on the given DependencyProperty.
    1152         /// </summary>
    1153         /// <remarks>
    1154         /// This does the same work as InvalidateSubProperty, and in addition
    1155         /// it raise the Freezable.Changed event if the current DependencyObject
    1156         /// is a Freezable.  This method should be called whenever an
    1157         /// intermediate object is responsible for propagating the Freezable.Changed
    1158         /// event (i.e. when the Freezable system doesn't propagate the event itself).
    1159         /// </remarks>
    1160         [FriendAccessAllowed] // Built into Base, also used by Framework.
    1161         internal void NotifySubPropertyChange(DependencyProperty dp)
    1162         {
    1163             InvalidateSubProperty(dp);
    1164  
    1165             // if the target is a Freezable, call FireChanged to kick off
    1166             // notifications to the Freezable's parent chain.
    1167             Freezable freezable = this as Freezable;
    1168             if (freezable != null)
    1169             {
    1170                 freezable.FireChanged();
    1171             }
    1172         }
    1173  
    1174         /// <summary>
    1175         ///     Invalidates a property
    1176         /// </summary>
    1177         /// <param name="dp">Dependency property</param>
    1178         //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647
    1179         public void InvalidateProperty(DependencyProperty dp)
    1180         {
    1181             InvalidateProperty(dp, preserveCurrentValue:false);
    1182         }
    1183  
    1184         // Invalidation, optionally preserving the current value if the base
    1185         // value doesn't change.
    1186         //  The flag is set only by triggers, as a workaround for a missing API.
    1187         // When we added SetCurrentValue, we should have also added ClearCurrentValue
    1188         // to give controls a way to remove the current value. Lacking that, controls use
    1189         // InvalidateProperty (VirtualizingStackPanel does this), relying on behavior
    1190         // that should also have been different - an invalidation that doesn't change
    1191         // the base value should preserve the current value.
    1192         //  This matters for triggers (see Dev11 bug 72825).  When any input to a
    1193         // trigger condition changes, the trigger simply invalidates all the properties
    1194         // mentioned in its setters.  These invalidations often discover no value change -
    1195         // (example:  Trigger condition is "IsVisible && HasErrors";  if IsVisible is false,
    1196         // changing input HasErrors won't change the condition value.   The dependent
    1197         // properties are invalidated, but they don't actually change value.)
    1198         //  To fix the bug, we are putting in the "preserve current value" behavior, but
    1199         // only for invalidations that come from triggers.
    1200         internal void InvalidateProperty(DependencyProperty dp, bool preserveCurrentValue)
    1201         {
    1202             // Do not allow foreign threads access.
    1203             // (This is a noop if this object is not assigned to a Dispatcher.)
    1204             //
    1205             this.VerifyAccess();
    1206  
    1207             if (dp == null)
    1208             {
    1209                 throw new ArgumentNullException("dp");
    1210             }
    1211  
    1212             EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Unknown);
    1213             newEntry.IsCoercedWithCurrentValue = preserveCurrentValue;
    1214  
    1215             UpdateEffectiveValue(
    1216                     LookupEntry(dp.GlobalIndex),
    1217                     dp,
    1218                     dp.GetMetadata(DependencyObjectType),
    1219                     new EffectiveValueEntry() /* oldEntry */,
    1220                     ref newEntry,
    1221                     false /* coerceWithDeferredReference */,
    1222                     false /* coerceWithCurrentValue */,
    1223                     OperationType.Unknown);
    1224         }
    1225  
    1226         //
    1227         //  This method
    1228         //  1. Re-evaluates the effective value for the given property and fires the property changed notification
    1229         //  2. When this method is invoked with the coersion flag set to false it means that we will simply
    1230         //     coerce and will not try to re-evaluate the base value for the property
    1231         //
    1232         [FriendAccessAllowed] // Declared in Base also used in Framework
    1233         internal UpdateResult UpdateEffectiveValue(
    1234                 EntryIndex          entryIndex,
    1235                 DependencyProperty  dp,
    1236                 PropertyMetadata    metadata,
    1237                 EffectiveValueEntry oldEntry,
    1238             ref EffectiveValueEntry newEntry,
    1239                 bool                coerceWithDeferredReference,
    1240                 bool                coerceWithCurrentValue,
    1241                 OperationType       operationType)
    1242         {
    1243             if (dp == null)
    1244             {
    1245                 throw new ArgumentNullException("dp");
    1246             }
    1247  
    1248 #region EventTracing
    1249 #if VERBOSE_PROPERTY_EVENT
    1250             bool isDynamicTracing = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); // This was under "normal"
    1251             if (isDynamicTracing)
    1252             {
    1253                 ++InvalidationCount;
    1254                 if( InvalidationCount % 100 == 0 )
    1255                 {
    1256                     EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID,
    1257                                                          MS.Utility.EventType.Info,
    1258                                                          InvalidationCount );
    1259                 }
    1260  
    1261                 string TypeAndName = String.Format(CultureInfo.InvariantCulture, "[{0}]{1}({2})",GetType().Name,dp.Name,base.GetHashCode()); // FxCop wanted the CultureInfo.InvariantCulture
    1262  
    1263                 EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID,
    1264                                                      MS.Utility.EventType.StartEvent,
    1265                                                      base.GetHashCode(), TypeAndName); // base.GetHashCode() to avoid calling a virtual, which FxCop doesn't like.
    1266             }
    1267 #endif
    1268  
    1269  
    1270 #endregion EventTracing
    1271  
    1272 #if NESTED_OPERATIONS_CHECK
    1273             // Are we invalidating out of control?
    1274             if( NestedOperations > NestedOperationMaximum )
    1275             {
    1276                 // We're invalidating out of control, time to abort.
    1277                 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.");
    1278             }
    1279             NestedOperations++; // Decrement in the finally block
    1280 #endif
    1281             int targetIndex = dp.GlobalIndex;
    1282  
    1283             if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown)
    1284             {
    1285                 // Do a full get value of the old entry if it isn't supplied.
    1286                 // It isn't supplied in cases where we are *unsetting* a value
    1287                 // (e.g. ClearValue, style unapply, trigger unapply)
    1288                 oldEntry = GetValueEntry(
    1289                                     entryIndex,
    1290                                     dp,
    1291                                     metadata,
    1292                                     RequestFlags.RawEntry);
    1293             }
    1294  
    1295             object oldValue = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value;
    1296  
    1297  
    1298             /*
    1299             if( TraceDependencyProperty.IsEnabled )
    1300             {
    1301                 TraceDependencyProperty.Trace(
    1302                     TraceEventType.Verbose,
    1303                     TraceDependencyProperty.UpdateEffectiveValueStart,
    1304                     this,
    1305                     dp,
    1306                     dp.OwnerType,
    1307                     oldValue,
    1308                     oldEntry.BaseValueSourceInternal );
    1309             }
    1310             */
    1311  
    1312             // for control-value coercion, extract the desired control value, then
    1313             // reset the new entry to ask for a re-evaluation with coercion
    1314             object controlValue = null;
    1315             if (coerceWithCurrentValue)
    1316             {
    1317                 controlValue = newEntry.Value;
    1318                 newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced);
    1319             }
    1320  
    1321             // check for early-out opportunities:
    1322             //  1) the new entry is of lower priority than the current entry
    1323             if ((newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Unknown) &&
    1324                 (newEntry.BaseValueSourceInternal < oldEntry.BaseValueSourceInternal))
    1325             {
    1326                 return 0;
    1327             }
    1328  
    1329             bool isReEvaluate = false;
    1330             bool isCoerceValue = false;
    1331             bool isClearValue = false;
    1332  
    1333             if (newEntry.Value == DependencyProperty.UnsetValue)
    1334             {
    1335                 FullValueSource fullValueSource = newEntry.FullValueSource;
    1336                 isCoerceValue = (fullValueSource == FullValueSource.IsCoerced);
    1337                 isReEvaluate = true;
    1338  
    1339                 if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Local)
    1340                 {
    1341                     isClearValue = true;
    1342                 }
    1343             }
    1344  
    1345             // if we're not in an animation update (caused by AnimationStorage.OnCurrentTimeInvalidated)
    1346             // then always force a re-evaluation if (a) there was an animation in play or (b) there's
    1347             // an expression evaluation to be made
    1348             if (isReEvaluate ||
    1349                 (!newEntry.IsAnimated &&
    1350                  (oldEntry.IsAnimated ||
    1351                  (oldEntry.IsExpression && newEntry.IsExpression && (newEntry.ModifiedValue.BaseValue == oldEntry.ModifiedValue.BaseValue)))))
    1352             {
    1353                 // we have to compute the new value
    1354                 if (!isCoerceValue)
    1355                 {
    1356                     newEntry = EvaluateEffectiveValue(entryIndex, dp, metadata, oldEntry, newEntry, operationType);
    1357  
    1358                     // Make sure that the call out did not cause a change to entryIndex
    1359                     entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1360  
    1361                     bool found = (newEntry.Value != DependencyProperty.UnsetValue);
    1362                     if (!found && metadata.IsInherited)
    1363                     {
    1364                         DependencyObject inheritanceParent = InheritanceParent;
    1365                         if (inheritanceParent != null)
    1366                         {
    1367                             // Fetch the IsDeferredValue flag from the InheritanceParent
    1368                             EntryIndex parentEntryIndex = inheritanceParent.LookupEntry(dp.GlobalIndex);
    1369                             if (parentEntryIndex.Found)
    1370                             {
    1371                                 found = true;
    1372                                 newEntry = inheritanceParent._effectiveValues[parentEntryIndex.Index].GetFlattenedEntry(RequestFlags.FullyResolved);
    1373                                 newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited;
    1374                             }
    1375                         }
    1376                     }
    1377  
    1378                     // interesting that I just had to add this ... suggests that we are now overinvalidating
    1379                     if (!found)
    1380                     {
    1381                         newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
    1382                     }
    1383                 }
    1384                 else
    1385                 {
    1386                     if (!oldEntry.HasModifiers)
    1387                     {
    1388                         newEntry = oldEntry;
    1389                     }
    1390                     else
    1391                     {
    1392                         newEntry = new EffectiveValueEntry(dp, oldEntry.BaseValueSourceInternal);
    1393                         ModifiedValue modifiedValue = oldEntry.ModifiedValue;
    1394                         object baseValue = modifiedValue.BaseValue;
    1395                         newEntry.Value = baseValue;
    1396                         newEntry.HasExpressionMarker = oldEntry.HasExpressionMarker;
    1397  
    1398                         if (oldEntry.IsExpression)
    1399                         {
    1400                             newEntry.SetExpressionValue(modifiedValue.ExpressionValue, baseValue);
    1401                         }
    1402  
    1403                         if (oldEntry.IsAnimated)
    1404                         {
    1405                             newEntry.SetAnimatedValue(modifiedValue.AnimatedValue, baseValue);
    1406                         }
    1407                     }
    1408                 }
    1409             }
    1410  
    1411             // Coerce to current value
    1412             if (coerceWithCurrentValue)
    1413             {
    1414                 object baseValue = newEntry.GetFlattenedEntry(RequestFlags.CoercionBaseValue).Value;
    1415  
    1416                 ProcessCoerceValue(
    1417                     dp,
    1418                     metadata,
    1419                     ref entryIndex,
    1420                     ref targetIndex,
    1421                     ref newEntry,
    1422                     ref oldEntry,
    1423                     ref oldValue,
    1424                     baseValue,
    1425                     controlValue,
    1426                     null /*coerceValueCallback */,
    1427                     coerceWithDeferredReference,
    1428                     coerceWithCurrentValue,
    1429                     false /*skipBaseValueChecks*/);
    1430  
    1431                 // Make sure that the call out did not cause a change to entryIndex
    1432                 entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1433             }
    1434  
    1435             // Coerce Value
    1436             if (metadata.CoerceValueCallback != null &&
    1437                 !(isClearValue && newEntry.FullValueSource == (FullValueSource)BaseValueSourceInternal.Default))
    1438             {
    1439                 // CALLBACK
    1440                 object baseValue = newEntry.GetFlattenedEntry(RequestFlags.CoercionBaseValue).Value;
    1441  
    1442                 ProcessCoerceValue(
    1443                     dp,
    1444                     metadata,
    1445                     ref entryIndex,
    1446                     ref targetIndex,
    1447                     ref newEntry,
    1448                     ref oldEntry,
    1449                     ref oldValue,
    1450                     baseValue,
    1451                     null /* controlValue */,
    1452                     metadata.CoerceValueCallback,
    1453                     coerceWithDeferredReference,
    1454                     false /* coerceWithCurrentValue */,
    1455                     false /*skipBaseValueChecks*/);
    1456  
    1457                 // Make sure that the call out did not cause a change to entryIndex
    1458                 entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1459             }
    1460  
    1461             // The main difference between this callback and the metadata.CoerceValueCallback is that
    1462             // designers want to be able to coerce during all value changes including a change to the
    1463             // default value. Whereas metadata.CoerceValueCallback coerces all property values but the
    1464             // default, because default values are meant to fit automatically fit into the coersion constraint.
    1465  
    1466             if (dp.DesignerCoerceValueCallback != null)
    1467             {
    1468                 // During a DesignerCoerceValueCallback the value obtained is stored in the same
    1469                 // member as the metadata.CoerceValueCallback. In this case we do not store the
    1470                 // baseValue in the entry. Thus the baseValue checks will the violated. That is the
    1471                 // reason for skipping these checks in this one case.
    1472  
    1473                 // Also before invoking the DesignerCoerceValueCallback the baseValue must
    1474                 // always be expanded if it is a DeferredReference
    1475  
    1476                 ProcessCoerceValue(
    1477                     dp,
    1478                     metadata,
    1479                     ref entryIndex,
    1480                     ref targetIndex,
    1481                     ref newEntry,
    1482                     ref oldEntry,
    1483                     ref oldValue,
    1484                     newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value,
    1485                     null /*controlValue*/,
    1486                     dp.DesignerCoerceValueCallback,
    1487                     false /*coerceWithDeferredReference*/,
    1488                     false /*coerceWithCurrentValue*/,
    1489                     true /*skipBaseValueChecks*/);
    1490  
    1491                 // Make sure that the call out did not cause a change to entryIndex
    1492                 entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1493             }
    1494  
    1495             UpdateResult result = 0;
    1496  
    1497             if (newEntry.FullValueSource != (FullValueSource) BaseValueSourceInternal.Default)
    1498             {
    1499                 Debug.Assert(newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Unknown, "Value source should be known at this point");
    1500                 bool unsetValue = false;
    1501  
    1502                 if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Inherited)
    1503                 {
    1504                     if (DependencyObject.IsTreeWalkOperation(operationType) &&
    1505                         (newEntry.IsCoerced || newEntry.IsAnimated))
    1506                     {
    1507                         // an inherited value has been coerced or animated.  This
    1508                         // should be treated as a new "set" of the property.
    1509                         // The current tree walk should not continue into the subtree,
    1510                         // but rather a new tree walk should start.
    1511  
    1512                         // this signals OnPropertyChanged to start a new tree walk
    1513                         // and mark the current node as SelfInheritanceParent
    1514                         operationType = OperationType.Unknown;
    1515  
    1516                         // this signals the caller not to continue the current
    1517                         // tree walk into the subtree
    1518                         result |= UpdateResult.InheritedValueOverridden;
    1519                     }
    1520                     else if (!IsSelfInheritanceParent)
    1521                     {
    1522                         // otherwise, just inherit the value from the InheritanceParent
    1523                         unsetValue = true;
    1524                     }
    1525                 }
    1526  
    1527                 if (unsetValue)
    1528                 {
    1529                     UnsetEffectiveValue(entryIndex, dp, metadata);
    1530                 }
    1531                 else
    1532                 {
    1533                     SetEffectiveValue(entryIndex, dp, metadata, newEntry, oldEntry);
    1534                 }
    1535             }
    1536             else
    1537             {
    1538                 UnsetEffectiveValue(entryIndex, dp, metadata);
    1539             }
    1540  
    1541             // Change notifications are fired when the value actually changed or in
    1542             // the case of the Freezable mutable factories when the value source changes.
    1543             // Try AvaCop without the second condition to repro this problem.
    1544             bool isAValueChange = !Equals(dp, oldValue, newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value);
    1545  
    1546             if (isAValueChange)
    1547             {
    1548                 result |= UpdateResult.ValueChanged;
    1549             }
    1550  
    1551             if (isAValueChange ||
    1552                 (operationType == OperationType.ChangeMutableDefaultValue && oldEntry.BaseValueSourceInternal != newEntry.BaseValueSourceInternal) ||
    1553                 (metadata.IsInherited && oldEntry.BaseValueSourceInternal != newEntry.BaseValueSourceInternal && operationType != OperationType.AddChild && operationType != OperationType.RemoveChild && operationType != OperationType.Inherit))
    1554             {
    1555                 result |= UpdateResult.NotificationSent;
    1556  
    1557                 try
    1558                 {
    1559                     // fire change notification
    1560                     NotifyPropertyChange(
    1561                             new DependencyPropertyChangedEventArgs(
    1562                                     dp,
    1563                                     metadata,
    1564                                     isAValueChange,
    1565                                     oldEntry,
    1566                                     newEntry,
    1567                                     operationType));
    1568                 }
    1569                 finally
    1570                 {
    1571 #if NESTED_OPERATIONS_CHECK
    1572                     NestedOperations--;
    1573 #endif
    1574                 }
    1575             }
    1576  
    1577 #region EventTracing
    1578 #if VERBOSE_PROPERTY_EVENT
    1579             if (isDynamicTracing)
    1580             {
    1581                 if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose))
    1582                 {
    1583                     EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, MS.Utility.EventType.EndEvent);
    1584                 }
    1585             }
    1586 #endif
    1587 #endregion EventTracing
    1588  
    1589  
    1590             /*
    1591             if( TraceDependencyProperty.IsEnabled )
    1592             {
    1593                 TraceDependencyProperty.Trace(
    1594                     TraceEventType.Verbose,
    1595                     TraceDependencyProperty.UpdateEffectiveValueStop,
    1596                     this, dp, dp.OwnerType,
    1597                     newEntry.Value, newEntry.BaseValueSourceInternal );
    1598             }
    1599             */
    1600  
    1601             // There are two cases in which we need to adjust inheritance contexts:
    1602             //
    1603             //     1.  The value pointed to this DP has changed, in which case
    1604             //         we need to move the context from the old value to the
    1605             //         new value.
    1606             //
    1607             //     2.  The value has not changed, but the ValueSource for the
    1608             //         property has.  (For example, we've gone from being a local
    1609             //         value to the result of a binding expression that just
    1610             //         happens to return the same DO instance.)  In which case
    1611             //         we may need to add or remove contexts even though we
    1612             //         did not raise change notifications.
    1613             //
    1614             // We don't want to provide an inheritance context if the entry is
    1615             // animated, coerced, is an expression, is coming from a style or
    1616             // template, etc.  To avoid this, we explicitly check that the
    1617             // FullValueSource is Local.  By checking FullValueSource rather than
    1618             // BaseValueSource we are implicitly filtering out any sources which
    1619             // have modifiers.  (e.g., IsExpression, IsAnimated, etc.)
    1620  
    1621             bool oldEntryHadContext = oldEntry.FullValueSource == (FullValueSource) BaseValueSourceInternal.Local;
    1622             bool newEntryNeedsContext = newEntry.FullValueSource == (FullValueSource) BaseValueSourceInternal.Local;
    1623  
    1624             // NOTE:  We use result rather than isAValueChange below so that we
    1625             //        pick up mutable default promotion, etc.
    1626             if (result != 0 || (oldEntryHadContext != newEntryNeedsContext))
    1627             {
    1628                 if (oldEntryHadContext)
    1629                 {
    1630                     // RemoveSelfAsInheritanceContext no-ops null, non-DO values, etc.
    1631                     RemoveSelfAsInheritanceContext(oldEntry.LocalValue, dp);
    1632                 }
    1633  
    1634                 // Become the context for the new value. This is happens after
    1635                 // invalidation so that FE has a chance to hookup the logical
    1636                 // tree first. This is done only if the current DependencyObject
    1637                 // wants to be in the InheritanceContext tree.
    1638                 if (newEntryNeedsContext)
    1639                 {
    1640                     // ProvideSelfAsInheritanceContext no-ops null, non-DO values, etc.
    1641                     ProvideSelfAsInheritanceContext(newEntry.LocalValue, dp);
    1642                 }
    1643  
    1644                 // DANGER:  Callout might add/remove entries in the effective value table.
    1645                 //          Uncomment the following if you need to use entryIndex post
    1646                 //          context hookup.
    1647                 //
    1648                 // entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
    1649             }
    1650  
    1651             return result;
    1652         }
    1653  
    1654         private void ProcessCoerceValue(
    1655             DependencyProperty dp,
    1656             PropertyMetadata metadata,
    1657             ref EntryIndex entryIndex,
    1658             ref int targetIndex,
    1659             ref EffectiveValueEntry newEntry,
    1660             ref EffectiveValueEntry oldEntry,
    1661             ref object oldValue,
    1662             object baseValue,
    1663             object controlValue,
    1664             CoerceValueCallback coerceValueCallback,
    1665             bool coerceWithDeferredReference,
    1666             bool coerceWithCurrentValue,
    1667             bool skipBaseValueChecks)
    1668         {
    1669             if (newEntry.IsDeferredReference)
    1670             {
    1671                 Debug.Assert(!(newEntry.IsCoerced && !newEntry.IsCoercedWithCurrentValue) &&
    1672                     !newEntry.IsAnimated, "Coerced or Animated value cannot be a deferred reference");
    1673  
    1674                 // Allow values to stay deferred through coercion callbacks in
    1675                 // limited circumstances, when we know the listener is internal.
    1676                 // Since we never assign DeferredReference instances to
    1677                 // non-internal (non-friend assembly) classes, it's safe to skip
    1678                 // the dereference if the callback is to the DP owner (and not
    1679                 // a derived type).  This is consistent with passing raw
    1680                 // DeferredReference instances to ValidateValue callbacks, which
    1681                 // only ever go to the owner class.
    1682                 if (!coerceWithDeferredReference ||
    1683                     dp.OwnerType != metadata.CoerceValueCallback.Method.DeclaringType) // Need 2nd check to rule out derived class callback overrides.
    1684                 {
    1685                     // Resolve deferred references because we need the actual
    1686                     // baseValue to evaluate the correct animated value. This is done
    1687                     // by invoking GetValue for this property.
    1688                     DeferredReference dr = (DeferredReference) baseValue;
    1689                     baseValue = dr.GetValue(newEntry.BaseValueSourceInternal);
    1690  
    1691                     // Set the baseValue back into the entry
    1692                     newEntry.SetCoersionBaseValue(baseValue);
    1693  
    1694                     entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1695                 }
    1696             }
    1697  
    1698             object coercedValue = coerceWithCurrentValue ? controlValue : coerceValueCallback(this, baseValue);
    1699  
    1700             // Make sure that the call out did not cause a change to entryIndex
    1701             entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1702  
    1703             // Even if we used the controlValue in the coerce callback, we still want to compare against the original baseValue
    1704             // to determine if we need to set a coerced value.
    1705             if (!Equals(dp, coercedValue, baseValue))
    1706             {
    1707                 // returning DependencyProperty.UnsetValue from a Coercion callback means "don't do the set" ...
    1708                 // or "use previous value"
    1709                 if (coercedValue == DependencyProperty.UnsetValue)
    1710                 {
    1711                     if (oldEntry.IsDeferredReference)
    1712                     {
    1713                         DeferredReference reference = (DeferredReference)oldValue;
    1714                         oldValue = reference.GetValue(oldEntry.BaseValueSourceInternal);
    1715  
    1716                         entryIndex = CheckEntryIndex(entryIndex, targetIndex);
    1717                     }
    1718  
    1719                     coercedValue = oldValue;
    1720                 }
    1721  
    1722                 // Note that we do not support the value being coerced to a
    1723                 // DeferredReference
    1724                 if (!dp.IsValidValue(coercedValue))
    1725                 {
    1726                     // well... unless it's the control's "current value"
    1727                     if (!(coerceWithCurrentValue && coercedValue is DeferredReference))
    1728                         throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, coercedValue, dp.Name));
    1729                 }
    1730  
    1731                 // Set the coerced value here. All other values would
    1732                 // have been set during EvaluateEffectiveValue/GetValueCore.
    1733  
    1734                 newEntry.SetCoercedValue(coercedValue, baseValue, skipBaseValueChecks, coerceWithCurrentValue);
    1735             }
    1736         }
    1737  
    1738         /// <summary>
    1739         /// This is a helper method that is used to fire the property change notification through
    1740         /// the callbacks and to all the dependents of this property such as bindings etc.
    1741         /// </summary>
    1742         [FriendAccessAllowed] // Built into Base, also used by Framework.
    1743         internal void NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
    1744         {
    1745             // fire change notification
    1746             OnPropertyChanged(args);
    1747  
    1748             if (args.IsAValueChange || args.IsASubPropertyChange)
    1749             {
    1750                 // Invalidate all Dependents of this Source invalidation due
    1751                 // to Expression dependencies
    1752  
    1753                 DependencyProperty dp = args.Property;
    1754                 object objectDependentsListMap = DependentListMapField.GetValue(this);
    1755                 if (objectDependentsListMap != null)
    1756                 {
    1757                     FrugalMap dependentListMap = (FrugalMap)objectDependentsListMap;
    1758                     object dependentList = dependentListMap[dp.GlobalIndex];
    1759                     Debug.Assert(dependentList != null, "dependentList should either be unset or non-null");
    1760  
    1761                     if (dependentList != DependencyProperty.UnsetValue)
    1762                     {
    1763                         // The list can "go empty" if the items it references "went away"
    1764                         if (((DependentList)dependentList).IsEmpty)
    1765                             dependentListMap[dp.GlobalIndex] = DependencyProperty.UnsetValue;
    1766                         else
    1767                             ((DependentList)dependentList).InvalidateDependents(this, args);
    1768                     }
    1769  
    1770                     // also notify "direct" dependents
    1771                     dp = DirectDependencyProperty;
    1772                     dependentList = dependentListMap[dp.GlobalIndex];
    1773                     Debug.Assert(dependentList != null, "dependentList should either be unset or non-null");
    1774  
    1775                     if (dependentList != DependencyProperty.UnsetValue)
    1776                     {
    1777                         // The list can "go empty" if the items it references "went away"
    1778                         if (((DependentList)dependentList).IsEmpty)
    1779                             dependentListMap[dp.GlobalIndex] = DependencyProperty.UnsetValue;
    1780                         else
    1781                             ((DependentList)dependentList).InvalidateDependents(this, new DependencyPropertyChangedEventArgs(dp, (PropertyMetadata)null, null));
    1782                     }
    1783                 }
    1784             }
    1785         }
    1786  
    1787  
    1788         private EffectiveValueEntry EvaluateExpression(
    1789             EntryIndex entryIndex,
    1790             DependencyProperty dp,
    1791             Expression expr,
    1792             PropertyMetadata metadata,
    1793             EffectiveValueEntry oldEntry,
    1794             EffectiveValueEntry newEntry)
    1795         {
    1796             object value = expr.GetValue(this, dp);
    1797             bool isDeferredReference = false;
    1798  
    1799             if (value != DependencyProperty.UnsetValue && value != Expression.NoValue)
    1800             {
    1801                 isDeferredReference = (value is DeferredReference);
    1802                 if (!isDeferredReference && !dp.IsValidValue(value))
    1803                 {
    1804 #region EventTracing
    1805 #if VERBOSE_PROPERTY_EVENT
    1806                     if (isDynamicTracing)
    1807                     {
    1808                         if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose))
    1809                         {
    1810                             EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYGUID,
    1811                                                                 MS.Utility.EventType.EndEvent,
    1812                                                                 EventTrace.PROPERTYVALIDATION, 0xFFF );
    1813                         }
    1814                     }
    1815 #endif
    1816 #endregion EventTracing
    1817                     throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));
    1818                 }
    1819             }
    1820             else
    1821             {
    1822                 if (value == Expression.NoValue)
    1823                 {
    1824                     // The expression wants to "hide".  First set the
    1825                     // expression value to NoValue to indicate "hiding".
    1826                     newEntry.SetExpressionValue(Expression.NoValue, expr);
    1827  
    1828                     // Next, get the expression value some other way.
    1829                     if (!dp.ReadOnly)
    1830                     {
    1831                         EvaluateBaseValueCore(dp, metadata, ref newEntry);
    1832                         value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value;
    1833                     }
    1834                     else
    1835                     {
    1836                         value = DependencyProperty.UnsetValue;
    1837                     }
    1838                 }
    1839  
    1840                 // if there is still no value, use the default
    1841                 if (value == DependencyProperty.UnsetValue)
    1842                 {
    1843                     value = metadata.GetDefaultValue(this, dp);
    1844                 }
    1845             }
    1846  
    1847             // Set the expr and its evaluated value into
    1848             // the _effectiveValues cache
    1849             newEntry.SetExpressionValue(value, expr);
    1850             return newEntry;
    1851         }
    1852  
    1853         //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647
    1854         private EffectiveValueEntry EvaluateEffectiveValue(
    1855             EntryIndex entryIndex,
    1856             DependencyProperty dp,
    1857             PropertyMetadata metadata,
    1858             EffectiveValueEntry oldEntry,
    1859             EffectiveValueEntry newEntry, // this is only used to recognize if this is a clear local value
    1860             OperationType operationType)
    1861         {
    1862 #region EventTracing
    1863 #if VERBOSE_PROPERTY_EVENT
    1864             bool isDynamicTracing = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); // This was under "normal"
    1865             if (isDynamicTracing)
    1866             {
    1867                 ++ValidationCount;
    1868                 if( ValidationCount % 100 == 0 )
    1869                 {
    1870                     EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID,
    1871                                                          MS.Utility.EventType.Info,
    1872                                                          ValidationCount );
    1873                 }
    1874  
    1875                 string TypeAndName = String.Format(CultureInfo.InvariantCulture, "[{0}]{1}({2})",GetType().Name,dp.Name,base.GetHashCode());  // FxCop wanted the CultureInfo.InvariantCulture
    1876  
    1877                 EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID,
    1878                                                      MS.Utility.EventType.StartEvent,
    1879                                                      base.GetHashCode(), TypeAndName ); // base.GetHashCode() to avoid calling a virtual, which FxCop doesn't like.
    1880             }
    1881 #endif
    1882 #endregion EventTracing
    1883  
    1884 #if NESTED_OPERATIONS_CHECK
    1885             // Are we validating out of control?
    1886             if( NestedOperations > NestedOperationMaximum )
    1887             {
    1888                 // We're validating out of control, time to abort.
    1889                 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.");
    1890             }
    1891             NestedOperations++; // Decrement in the finally block
    1892 #endif
    1893  
    1894             object value = DependencyProperty.UnsetValue;
    1895  
    1896             try
    1897             {
    1898                 // Read local storage
    1899                 bool isSetValue = (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Local);
    1900                 bool isClearLocalValue = isSetValue && (newEntry.Value == DependencyProperty.UnsetValue);
    1901                 bool oldLocalIsExpression = false;
    1902                 bool preserveCurrentValue;
    1903  
    1904                 // honor request for "preserve current value" behaviour - see InvalidateProperty.
    1905                 if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown &&
    1906                     newEntry.IsCoercedWithCurrentValue)
    1907                 {
    1908                     preserveCurrentValue = true;
    1909                     newEntry.IsCoercedWithCurrentValue = false;     // clear flag only used for private communication
    1910                 }
    1911                 else
    1912                 {
    1913                     preserveCurrentValue = false;
    1914                 }
    1915  
    1916                 if (isClearLocalValue)
    1917                 {
    1918                     newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Unknown;
    1919                 }
    1920                 else
    1921                 {
    1922                     // if we reached this on a re-evaluate of a setvalue, we need to make sure
    1923                     // we don't lose track of the newly specified local value.
    1924                     // for all other cases, the oldEntry will have the local value we should
    1925                     // use.
    1926                     value = isSetValue ? newEntry.LocalValue : oldEntry.LocalValue;
    1927  
    1928                     if (value == ExpressionInAlternativeStore)
    1929                     {
    1930                         value = DependencyProperty.UnsetValue;
    1931                     }
    1932                     else
    1933                     {
    1934                         oldLocalIsExpression = isSetValue ? newEntry.IsExpression : oldEntry.IsExpression;
    1935                     }
    1936                 }
    1937  
    1938                 // (If local storage not Unset and not an Expression, return)
    1939                 if (value != DependencyProperty.UnsetValue)
    1940                 {
    1941                     newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);
    1942                     newEntry.Value = value;
    1943  
    1944                     // Check if an Expression is set
    1945                     if (oldLocalIsExpression)
    1946                     {
    1947                         // CALLBACK
    1948                         newEntry = EvaluateExpression(
    1949                             entryIndex,
    1950                             dp,
    1951                             (Expression) value,
    1952                             metadata,
    1953                             oldEntry,
    1954                             newEntry);
    1955  
    1956                         entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
    1957  
    1958                         value = newEntry.ModifiedValue.ExpressionValue;
    1959                     }
    1960                 }
    1961  
    1962                 // Subclasses are not allowed to resolve/modify the value for read-only properties.
    1963                 if( !dp.ReadOnly )
    1964                 {
    1965                     // Give subclasses a chance to resolve/modify the value
    1966                     EvaluateBaseValueCore(dp, metadata, ref newEntry);
    1967  
    1968                     // we need to have the default value in the entry before we do the animation check
    1969                     if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown)
    1970                     {
    1971                         newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
    1972                     }
    1973  
    1974                     value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value;
    1975  
    1976                     // preserve a current value across invalidations that don't change
    1977                     // the base value
    1978                     if (preserveCurrentValue &&
    1979                         oldEntry.IsCoercedWithCurrentValue &&
    1980                         oldEntry.BaseValueSourceInternal == newEntry.BaseValueSourceInternal &&
    1981                         Equals(dp, oldEntry.ModifiedValue.BaseValue, value))
    1982                     {
    1983                         object currentValue = oldEntry.ModifiedValue.CoercedValue;
    1984                         newEntry.SetCoercedValue(currentValue, value, skipBaseValueChecks:true, coerceWithCurrentValue:true);
    1985                         value = currentValue;
    1986                     }
    1987  
    1988                     entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
    1989  
    1990                     if (oldEntry.IsAnimated)
    1991                     {
    1992                         newEntry.ResetCoercedValue();
    1993                         EvaluateAnimatedValueCore(dp, metadata, ref newEntry);
    1994                         value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value;
    1995                     }
    1996                 }
    1997             }
    1998             finally
    1999             {
    2000 #if NESTED_OPERATIONS_CHECK
    2001                 NestedOperations--;
    2002 #endif
    2003             }
    2004  
    2005 #region EventTracing
    2006 #if VERBOSE_PROPERTY_EVENT
    2007             if (isDynamicTracing)
    2008             {
    2009                 if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose))
    2010                 {
    2011                     int UsingDefault = 1;
    2012                     if (value != DependencyProperty.UnsetValue)
    2013                         UsingDefault = 0;
    2014                     EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID,
    2015                                                          MS.Utility.EventType.EndEvent,
    2016                                                          UsingDefault);
    2017                 }
    2018             }
    2019 #endif
    2020 #endregion EventTracing
    2021  
    2022             if (value == DependencyProperty.UnsetValue)
    2023             {
    2024                 newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));
    2025             }
    2026  
    2027             return newEntry;
    2028         }
    2029  
    2030         /// <summary>
    2031         ///     Allows subclasses to participate in property base value computation
    2032         /// </summary>
    2033         internal virtual void EvaluateBaseValueCore(
    2034                 DependencyProperty  dp,
    2035                 PropertyMetadata    metadata,
    2036             ref EffectiveValueEntry newEntry)
    2037         {
    2038         }
    2039  
    2040         /// <summary>
    2041         ///     Allows subclasses to participate in property animated value computation
    2042         /// </summary>
    2043         internal virtual void EvaluateAnimatedValueCore(
    2044                 DependencyProperty  dp,
    2045                 PropertyMetadata    metadata,
    2046             ref EffectiveValueEntry newEntry)
    2047         {
    2048         }
    2049  
    2050         /// <summary>
    2051         ///     Notification that a specified property has been changed
    2052         /// </summary>
    2053         /// <param name="e">EventArgs that contains the property, metadata, old value, and new value for this change</param>
    2054         protected virtual void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    2055         {
    2056             // Do not call VerifyAccess because this is a virtual, and is used as a call-out.
    2057  
    2058             if( e.Property == null )
    2059             {
    2060                 throw new ArgumentException(SR.Get(SRID.ReferenceIsNull, "e.Property"), "e");
    2061             }
    2062  
    2063             if (e.IsAValueChange || e.IsASubPropertyChange || e.OperationType == OperationType.ChangeMutableDefaultValue)
    2064             {
    2065                 // Inform per-type/property invalidation listener, if exists
    2066                 PropertyMetadata metadata = e.Metadata;
    2067                 if ((metadata != null) && (metadata.PropertyChangedCallback != null))
    2068                 {
    2069                     metadata.PropertyChangedCallback(this, e);
    2070                 }
    2071             }
    2072         }
    2073  
    2074         /// <summary>
    2075         /// Override this method to control whether a DependencyProperty should be serialized.
    2076         /// The base implementation returns true if the property is set (locally) on this object.
    2077         /// </summary>
    2078         protected internal virtual bool ShouldSerializeProperty( DependencyProperty dp )
    2079         {
    2080             return ContainsValue( dp );
    2081         }
    2082  
    2083         [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    2084         internal BaseValueSourceInternal GetValueSource(DependencyProperty dp, PropertyMetadata metadata, out bool hasModifiers)
    2085         {
    2086             bool isExpression, isAnimated, isCoerced, isCurrent;
    2087             return GetValueSource(dp, metadata, out hasModifiers, out isExpression, out isAnimated, out isCoerced, out isCurrent);
    2088         }
    2089  
    2090         [FriendAccessAllowed] // Built into Base, also used by Core & Framework.
    2091         internal BaseValueSourceInternal GetValueSource(DependencyProperty dp, PropertyMetadata metadata,
    2092                 out bool hasModifiers, out bool isExpression, out bool isAnimated, out bool isCoerced, out bool isCurrent)
    2093         {
    2094             if (dp == null)
    2095             {
    2096                 throw new ArgumentNullException("dp");
    2097             }
    2098  
    2099             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
    2100  
    2101             if (entryIndex.Found)
    2102             {
    2103                 EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
    2104                 hasModifiers = entry.HasModifiers;
    2105                 isExpression = entry.IsExpression;
    2106                 isAnimated = entry.IsAnimated;
    2107                 isCoerced = entry.IsCoerced;
    2108                 isCurrent = entry.IsCoercedWithCurrentValue;
    2109                 return entry.BaseValueSourceInternal;
    2110             }
    2111             else
    2112             {
    2113                 isExpression = false;
    2114                 isAnimated = false;
    2115                 isCoerced = false;
    2116                 isCurrent = false;
    2117  
    2118                 if (dp.ReadOnly)
    2119                 {
    2120                     if (metadata == null)
    2121                     {
    2122                         metadata = dp.GetMetadata(DependencyObjectType);
    2123                     }
    2124  
    2125                     GetReadOnlyValueCallback callback = metadata.GetReadOnlyValueCallback;
    2126                     if (callback != null)
    2127                     {
    2128                         BaseValueSourceInternal source;
    2129                         callback(this, out source);
    2130                         hasModifiers = false;
    2131                         return source;
    2132                     }
    2133                 }
    2134  
    2135                 if (dp.IsPotentiallyInherited)
    2136                 {
    2137                     if (metadata == null)
    2138                     {
    2139                         metadata = dp.GetMetadata(DependencyObjectType);
    2140                     }
    2141  
    2142                     if (metadata.IsInherited)
    2143                     {
    2144                         DependencyObject inheritanceParent = InheritanceParent;
    2145                         if (inheritanceParent != null && inheritanceParent.LookupEntry(dp.GlobalIndex).Found)
    2146                         {
    2147                             hasModifiers = false;
    2148                             return BaseValueSourceInternal.Inherited;
    2149                         }
    2150                     }
    2151                 }
    2152             }
    2153  
    2154             hasModifiers = false;
    2155             return BaseValueSourceInternal.Default;
    2156         }
    2157  
    2158         /// <summary>
    2159         ///     Retrieve the local value of a property (if set)
    2160         /// </summary>
    2161         /// <param name="dp">Dependency property</param>
    2162         /// <returns>
    2163         ///     The local value. DependencyProperty.UnsetValue if no local value was
    2164         ///     set via <cref see="SetValue"/>.
    2165         /// </returns>
    2166         public object ReadLocalValue(DependencyProperty dp)
    2167         {
    2168             // Do not allow foreign threads access.
    2169             // (This is a noop if this object is not assigned to a Dispatcher.)
    2170             //
    2171             this.VerifyAccess();
    2172  
    2173             if (dp == null)
    2174             {
    2175                 throw new ArgumentNullException("dp");
    2176             }
    2177  
    2178             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
    2179  
    2180             // Call Forwarded
    2181             return ReadLocalValueEntry(entryIndex, dp, false /* allowDeferredReferences */);
    2182         }
    2183  
    2184         /// <summary>
    2185         ///     Retrieve the local value of a property (if set)
    2186         /// </summary>
    2187         /// <returns>
    2188         ///     The local value. DependencyProperty.UnsetValue if no local value was
    2189         ///     set via <cref see="SetValue"/>.
    2190         /// </returns>
    2191         internal object ReadLocalValueEntry(EntryIndex entryIndex, DependencyProperty dp, bool allowDeferredReferences)
    2192         {
    2193             if (!entryIndex.Found)
    2194             {
    2195                 return DependencyProperty.UnsetValue;
    2196             }
    2197  
    2198             EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
    2199             object value = entry.IsCoercedWithCurrentValue ? entry.ModifiedValue.CoercedValue : entry.LocalValue;
    2200  
    2201             // convert a deferred reference into a real value
    2202             if (!allowDeferredReferences && entry.IsDeferredReference)
    2203             {
    2204                 // localValue may still not be a DeferredReference, e.g.
    2205                 // if it is an expression whose value is a DeferredReference.
    2206                 // So a little more work is needed before converting the value.
    2207                 DeferredReference dr = value as DeferredReference;
    2208                 if (dr != null)
    2209                 {
    2210                     value = dr.GetValue(entry.BaseValueSourceInternal);
    2211                 }
    2212             }
    2213  
    2214             // treat Expression marker as "unset"
    2215             if (value == ExpressionInAlternativeStore)
    2216             {
    2217                 value = DependencyProperty.UnsetValue;
    2218             }
    2219  
    2220             return value;
    2221         }
    2222  
    2223         /// <summary>
    2224         ///     Create a local value enumerator for this instance
    2225         /// </summary>
    2226         /// <returns>Local value enumerator (stack based)</returns>
    2227         public LocalValueEnumerator GetLocalValueEnumerator()
    2228         {
    2229             // Do not allow foreign threads access.
    2230             // (This is a noop if this object is not assigned to a Dispatcher.)
    2231             //
    2232             this.VerifyAccess();
    2233  
    2234             uint effectiveValuesCount = EffectiveValuesCount;
    2235             LocalValueEntry[] snapshot = new LocalValueEntry[effectiveValuesCount];
    2236             int count = 0;
    2237  
    2238             // Iterate through the sorted effectiveValues
    2239             for (uint i=0; i<effectiveValuesCount; i++)
    2240             {
    2241                 DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[_effectiveValues[i].PropertyIndex];
    2242                 if (dp != null)
    2243                 {
    2244                     object localValue = ReadLocalValueEntry(new EntryIndex(i), dp, false /* allowDeferredReferences */);
    2245                     if (localValue != DependencyProperty.UnsetValue)
    2246                     {
    2247                         snapshot[count++] = new LocalValueEntry(dp, localValue);
    2248                     }
    2249                 }
    2250             }
    2251  
    2252             return new LocalValueEnumerator(snapshot, count);
    2253         }
    2254  
    2255         /// <summary>
    2256         ///     This is how we track if someone is enumerating the _effectiveValues
    2257         ///     cache. This flag should be set to false before doing that.
    2258         /// </summary>
    2259         private bool CanModifyEffectiveValues
    2260         {
    2261             get { return (_packedData & 0x00080000) != 0; }
    2262  
    2263             set
    2264             {
    2265                 Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    2266  
    2267                 if (value)
    2268                 {
    2269                     _packedData |= 0x00080000;
    2270                 }
    2271                 else
    2272                 {
    2273                     _packedData &= 0xFFF7FFFF;
    2274                 }
    2275             }
    2276         }
    2277  
    2278         [FriendAccessAllowed]   // defined in Base, used in Core and Framework
    2279         internal bool IsInheritanceContextSealed
    2280         {
    2281             get { return (_packedData & 0x01000000) != 0; }
    2282             set
    2283             {
    2284                 if (value)
    2285                 {
    2286                     _packedData |= 0x01000000;
    2287                 }
    2288                 else
    2289                 {
    2290                     _packedData &= 0xFEFFFFFF;
    2291                 }
    2292             }
    2293         }
    2294  
    2295         private bool DO_Sealed
    2296         {
    2297             get { return (_packedData & 0x00400000) != 0; }
    2298             set { if (value) { _packedData |= 0x00400000; } else { _packedData &= 0xFFBFFFFF; } }
    2299         }
    2300  
    2301         // Freezable State stored here for size optimization:
    2302         // Freezable is immutable
    2303         internal bool Freezable_Frozen
    2304         {
    2305             // uses the same bit as Sealed ... even though they are not quite synonymous
    2306             // Since Frozen implies Sealed, and calling Seal() is disallowed on Freezable,
    2307             // this is ok.
    2308             get { return DO_Sealed; }
    2309             set { DO_Sealed = value; }
    2310         }
    2311  
    2312         // Freezable State stored here for size optimization:
    2313         // Freezable is being referenced in multiple places and hence cannot have a single InheritanceContext
    2314         internal bool Freezable_HasMultipleInheritanceContexts
    2315         {
    2316             get { return (_packedData & 0x02000000) != 0; }
    2317             set { if (value) { _packedData |= 0x02000000; } else { _packedData &= 0xFDFFFFFF; } }
    2318         }
    2319  
    2320         // Freezable State stored here for size optimization:
    2321         // Handlers stored in a dictionary
    2322         internal bool Freezable_UsingHandlerList
    2323         {
    2324             get { return (_packedData & 0x04000000) != 0; }
    2325             set { if (value) { _packedData |= 0x04000000; } else { _packedData &= 0xFBFFFFFF; } }
    2326         }
    2327  
    2328         // Freezable State stored here for size optimization:
    2329         // Context stored in a dictionary
    2330         internal bool Freezable_UsingContextList
    2331         {
    2332             get { return (_packedData & 0x08000000) != 0; }
    2333             set { if (value) { _packedData |= 0x08000000; } else { _packedData &= 0xF7FFFFFF; } }
    2334         }
    2335  
    2336         // Freezable State stored here for size optimization:
    2337         // Freezable has a single handler
    2338         internal bool Freezable_UsingSingletonHandler
    2339         {
    2340             get { return (_packedData & 0x10000000) != 0; }
    2341             set { if (value) { _packedData |= 0x10000000; } else { _packedData &= 0xEFFFFFFF; } }
    2342         }
    2343  
    2344         // Freezable State stored here for size optimization:
    2345         // Freezable has a single context
    2346         internal bool Freezable_UsingSingletonContext
    2347         {
    2348             get { return (_packedData & 0x20000000) != 0; }
    2349             set { if (value) { _packedData |= 0x20000000; } else { _packedData &= 0xDFFFFFFF; } }
    2350         }
    2351  
    2352  
    2353         // Animatable State stored here for size optimization:
    2354         //
    2355         internal bool Animatable_IsResourceInvalidationNecessary
    2356         {
    2357             [FriendAccessAllowed] // Built into Base, but used by Core.
    2358             get { return (_packedData & 0x40000000) != 0; }
    2359             [FriendAccessAllowed] // Built into Base, but used by Core.
    2360             set { if (value) { _packedData |= 0x40000000; } else { _packedData &= 0xBFFFFFFF; } }
    2361         }
    2362  
    2363         // IAnimatable State stored here for size optimization:
    2364         // Returns true if this IAnimatable implemention has animations on its properties
    2365         // but doesn't check the sub-properties for animations.
    2366         internal bool IAnimatable_HasAnimatedProperties
    2367         {
    2368             [FriendAccessAllowed] // Built into Base, but used by Core.
    2369             get { return (_packedData & 0x80000000) != 0; }
    2370             [FriendAccessAllowed] // Built into Base, but used by Core.
    2371             set { if (value) { _packedData |= 0x80000000; } else { _packedData &= 0x7FFFFFFF; } }
    2372         }
    2373  
    2374         // internal DP used for direct dependencies (should never appear in an effective value table)
    2375         //
    2376         // A direct dependency can arise from WPF data binding in a situation like this:
    2377         //      <Border Background="{Binding Path=Brush}"/>
    2378         // when the Brush property on the source object is not a DP, but just a regular CLR property.
    2379         // If a property on the brush changes, the border should be notified so that
    2380         // it can repaint its background. The brush is notified of the change, and
    2381         // propagtes the notification (as a SubPropertyChange) to all its customers that
    2382         // use the brush via a DP, but this isn't enough for the current scenario.
    2383         // To overcome this, the binding registers itself as a "direct" dependent of the brush
    2384         // (using the following DP as the key).  The property engine will forward
    2385         // notifications to direct dependents, the binding will hear about the change,
    2386         // and will forward a sub-property change to the Border.
    2387         [FriendAccessAllowed] // Built into Base, also used by Framework.
    2388         static internal readonly DependencyProperty DirectDependencyProperty =
    2389             DependencyProperty.Register("__Direct", typeof(object), typeof(DependencyProperty));
    2390  
    2391         internal static void UpdateSourceDependentLists(DependencyObject d, DependencyProperty dp, DependencySource[] sources, Expression expr, bool add)
    2392         {
    2393             // Sources already validated to be on the same thread as Dependent (d)
    2394  
    2395             if (sources != null)
    2396             {
    2397                 // don't hold a reference on the dependent if the expression is doing
    2398                 // the invalidations.  This helps avoid memory leaks (bug 871139)
    2399                 if (expr.ForwardsInvalidations)
    2400                 {
    2401                     d = null;
    2402                     dp = null;
    2403                 }
    2404  
    2405                 for (int i = 0; i < sources.Length; i++)
    2406                 {
    2407                     DependencySource source = sources[i];
    2408  
    2409                     // A Sealed DependencyObject does not have a Dependents list
    2410                     // so don't bother updating it (or attempt to add one).
    2411  
    2412                     Debug.Assert((!source.DependencyObject.IsSealed) ||
    2413                             (DependentListMapField.GetValue(source.DependencyObject) == default(object)));
    2414  
    2415                     if (!source.DependencyObject.IsSealed)
    2416                     {
    2417                         // Retrieve the DependentListMap for this source
    2418                         // The list of dependents to invalidate is stored using a special negative key
    2419  
    2420                         FrugalMap dependentListMap;
    2421                         object value = DependentListMapField.GetValue(source.DependencyObject);
    2422                         if (value != null)
    2423                         {
    2424                             dependentListMap = (FrugalMap)value;
    2425                         }
    2426                         else
    2427                         {
    2428                             dependentListMap = new FrugalMap();
    2429                         }
    2430  
    2431                         // Get list of DependentList off of ID map of Source
    2432                         object dependentListObj = dependentListMap[source.DependencyProperty.GlobalIndex];
    2433                         Debug.Assert(dependentListObj != null, "dependentList should either be unset or non-null");
    2434  
    2435                         // Add/Remove new Dependent (this) to Source's list
    2436                         if (add)
    2437                         {
    2438                             DependentList dependentList;
    2439                             if (dependentListObj == DependencyProperty.UnsetValue)
    2440                             {
    2441                                 dependentListMap[source.DependencyProperty.GlobalIndex] = dependentList = new DependentList();
    2442                             }
    2443                             else
    2444                             {
    2445                                 dependentList = (DependentList)dependentListObj;
    2446                             }
    2447  
    2448                             dependentList.Add(d, dp, expr);
    2449                         }
    2450                         else
    2451                         {
    2452                             if (dependentListObj != DependencyProperty.UnsetValue)
    2453                             {
    2454                                 DependentList dependentList = (DependentList)dependentListObj;
    2455  
    2456                                 dependentList.Remove(d, dp, expr);
    2457  
    2458                                 if (dependentList.IsEmpty)
    2459                                 {
    2460                                     // No more dependencies for this property; reclaim the space if we can.
    2461                                     dependentListMap[source.DependencyProperty.GlobalIndex] = DependencyProperty.UnsetValue;
    2462                                 }
    2463                             }
    2464                         }
    2465  
    2466                         // Set the updated struct back into the source's _localStore.
    2467                         DependentListMapField.SetValue(source.DependencyObject, dependentListMap);
    2468                     }
    2469                 }
    2470             }
    2471         }
    2472  
    2473         internal static void ValidateSources(DependencyObject d, DependencySource[] newSources, Expression expr)
    2474         {
    2475             // Make sure all Sources are owned by the same thread.
    2476             if (newSources != null)
    2477             {
    2478                 Dispatcher dispatcher = d.Dispatcher;
    2479                 for (int i = 0; i < newSources.Length; i++)
    2480                 {
    2481                     Dispatcher sourceDispatcher = newSources[i].DependencyObject.Dispatcher;
    2482                     if (sourceDispatcher != dispatcher && !(expr.SupportsUnboundSources && sourceDispatcher == null))
    2483                     {
    2484                         throw new ArgumentException(SR.Get(SRID.SourcesMustBeInSameThread));
    2485                     }
    2486                 }
    2487             }
    2488         }
    2489  
    2490         /// <summary>
    2491         /// Register the two callbacks that are used to implement the "alternative
    2492         /// Expression storage" feature, and return the two methods used to access
    2493         /// the feature.
    2494         /// </summary>
    2495         /// <remarks>
    2496         /// This method should only be called (once) from the Framework.  It should
    2497         /// not be called directly by users.
    2498         /// </remarks>
    2499         [FriendAccessAllowed] // Built into Base, also used by Framework.
    2500         internal static void RegisterForAlternativeExpressionStorage(
    2501                             AlternativeExpressionStorageCallback getExpressionCore,
    2502                             out AlternativeExpressionStorageCallback getExpression)
    2503         {
    2504             Debug.Assert(getExpressionCore != null, "getExpressionCore cannot be null");
    2505             Debug.Assert(_getExpressionCore == null, "The 'alternative Expression storage' feature has already been registered");
    2506  
    2507             _getExpressionCore = getExpressionCore;
    2508  
    2509             getExpression = new AlternativeExpressionStorageCallback(GetExpression);
    2510         }
    2511  
    2512         /// <summary>
    2513         /// Used to determine whether a DependencyObject has a value with an expression, such as a resource reference.
    2514         /// </summary>
    2515         /// <returns>
    2516         /// True if Dependency object has a value with an expression
    2517         /// </returns>
    2518         internal bool HasAnyExpression()
    2519         {
    2520             EffectiveValueEntry[] effectiveValues = EffectiveValues;
    2521             uint numEffectiveValues = EffectiveValuesCount;
    2522             bool result = false;
    2523  
    2524             for (uint i = 0; i < numEffectiveValues; i++)
    2525             {
    2526                 DependencyProperty dp =
    2527                     DependencyProperty.RegisteredPropertyList.List[effectiveValues[i].PropertyIndex];
    2528  
    2529                 if (dp != null)
    2530                 {
    2531                     EntryIndex entryIndex = new EntryIndex(i);
    2532                     // The expression check only needs to be done when isChecking is true
    2533                     // because if we return false here the Freeze() call will fail.
    2534                     if (HasExpression(entryIndex, dp))
    2535                     {
    2536                         result = true;
    2537                         break;
    2538                     }
    2539                 }
    2540             }
    2541  
    2542             return result;
    2543         }
    2544  
    2545         /// <summary>
    2546         /// Return true iff the property has an expression applied to it.
    2547         /// </summary>
    2548         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
    2549         internal bool HasExpression(EntryIndex entryIndex, DependencyProperty dp)
    2550         {
    2551             if (!entryIndex.Found)
    2552             {
    2553                 return false;
    2554             }
    2555  
    2556             EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
    2557  
    2558             object o = entry.LocalValue;
    2559  
    2560             bool result = (entry.HasExpressionMarker || o is Expression);
    2561             return result;
    2562         }
    2563  
    2564         /// <summary>
    2565         /// Return the Expression (if any) currently in effect for the given property.
    2566         /// </summary>
    2567         private static Expression GetExpression(DependencyObject d, DependencyProperty dp, PropertyMetadata metadata)
    2568         {
    2569             EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex);
    2570  
    2571             if (!entryIndex.Found)
    2572             {
    2573                 return null;
    2574             }
    2575  
    2576             EffectiveValueEntry entry = d._effectiveValues[entryIndex.Index];
    2577  
    2578             if (entry.HasExpressionMarker)
    2579             {
    2580                 if (_getExpressionCore != null)
    2581                 {
    2582                     return _getExpressionCore(d, dp, metadata);
    2583                 }
    2584  
    2585                 return null;
    2586             }
    2587  
    2588             // no expression marker -- check local value itself
    2589             if (entry.IsExpression)
    2590             {
    2591                 return (Expression) entry.LocalValue;
    2592             }
    2593  
    2594             return null;
    2595         }
    2596  
    2597         #region InheritanceContext
    2598  
    2599         /// <summary>
    2600         ///     InheritanceContext
    2601         /// </summary>
    2602         internal virtual DependencyObject InheritanceContext
    2603         {
    2604             [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
    2605             get { return null; }
    2606         }
    2607  
    2608         /// <summary>
    2609         ///     You have a new InheritanceContext
    2610         /// </summary>
    2611         /// <remarks>
    2612         ///     This method is equivalent to OnNewParent of
    2613         ///     the yesteryears on an element. Note that the
    2614         ///     implementation may choose to ignore this new
    2615         ///     context, e.g. in the case of a Freezable that
    2616         ///     is being shared.
    2617         ///     <p/>
    2618         ///     Do not call this method directly.  Instead call
    2619         ///     ProvideSelfAsInheritanceContext, which checks various
    2620         ///     preconditions and then calls AddInheritanceContext for you.
    2621         /// </remarks>
    2622         internal virtual void AddInheritanceContext(DependencyObject context, DependencyProperty property)
    2623         {
    2624         }
    2625  
    2626         /// <summary>
    2627         ///     You have lost an InheritanceContext
    2628         /// </summary>
    2629         /// <remarks>
    2630         ///     <p/>
    2631         ///     Do not call this method directly.  Instead call
    2632         ///     RemoveSelfAsInheritanceContext, which checks various
    2633         ///     preconditions and then calls RemoveInheritanceContext for you.
    2634         /// </remarks>
    2635         internal virtual void RemoveInheritanceContext(DependencyObject context, DependencyProperty property)
    2636         {
    2637         }
    2638  
    2639         /// <summary>
    2640         ///     You are about to provided as the InheritanceContext for the target.
    2641         ///     You can choose to allow this or not.
    2642         /// </summary>
    2643         internal virtual bool ShouldProvideInheritanceContext(DependencyObject target, DependencyProperty property)
    2644         {
    2645             return true;
    2646         }
    2647  
    2648         /// <summary>
    2649         ///     The InheritanceContext for an ancestor
    2650         ///     has changed
    2651         /// </summary>
    2652         /// <remarks>
    2653         ///     This is the equivalent of OnAncestorChanged
    2654         ///     for an element
    2655         /// </remarks>
    2656         [FriendAccessAllowed] // Built into Base, also used by Core.
    2657         internal void OnInheritanceContextChanged(EventArgs args)
    2658         {
    2659             // Fire the event that BindingExpression and
    2660             // ResourceReferenceExpression will be listening to.
    2661             EventHandler handlers = InheritanceContextChangedHandlersField.GetValue(this);
    2662             if (handlers != null)
    2663             {
    2664                 handlers(this, args);
    2665             }
    2666  
    2667             CanModifyEffectiveValues = false;
    2668             try
    2669             {
    2670                 // Notify all those DO that the current instance is a
    2671                 // context for (we will call these inheritanceChildren) about the
    2672                 // change in the context. This is like a recursive tree walk.
    2673                 // Iterate through the sorted effectiveValues
    2674                 uint effectiveValuesCount = EffectiveValuesCount;
    2675                 for (uint i=0; i<effectiveValuesCount; i++)
    2676                 {
    2677                     DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[_effectiveValues[i].PropertyIndex];
    2678                     if (dp != null)
    2679                     {
    2680                         object localValue = ReadLocalValueEntry(new EntryIndex(i), dp, true /* allowDeferredReferences */);
    2681                         if (localValue != DependencyProperty.UnsetValue)
    2682                         {
    2683                             DependencyObject inheritanceChild = localValue as DependencyObject;
    2684                             if (inheritanceChild!= null && inheritanceChild.InheritanceContext == this)
    2685                             {
    2686                                 inheritanceChild.OnInheritanceContextChanged(args);
    2687                             }
    2688                         }
    2689                     }
    2690                 }
    2691             }
    2692             finally
    2693             {
    2694                 Debug.Assert(CanModifyEffectiveValues == false, "We do not expect re-entrancy here.");
    2695                 CanModifyEffectiveValues = true;
    2696             }
    2697  
    2698             // Let sub-classes do their own thing
    2699             OnInheritanceContextChangedCore(args);
    2700         }
    2701  
    2702         /// <summary>
    2703         ///     This is a means for subclasses to get notification
    2704         ///     of InheritanceContext changes and then they can do
    2705         ///     their own thing.
    2706         /// </summary>
    2707         [FriendAccessAllowed] // Built into Base, also used by Core.
    2708         internal virtual void OnInheritanceContextChangedCore(EventArgs args)
    2709         {
    2710         }
    2711  
    2712         /// <summary>
    2713         ///     Event for InheritanceContextChanged. This is
    2714         ///     the event that BindingExpression and
    2715         ///     ResourceReferenceExpressions will be listening to.
    2716         /// </summary>
    2717         /// <remarks>
    2718         ///     make this pay-for-play by storing handlers
    2719         ///     in an uncommon field
    2720         /// </remarks>
    2721         internal event EventHandler InheritanceContextChanged
    2722         {
    2723             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2724             add
    2725             {
    2726                 // Get existing event hanlders
    2727                 EventHandler handlers = InheritanceContextChangedHandlersField.GetValue(this);
    2728                 if (handlers != null)
    2729                 {
    2730                     // combine to a multicast delegate
    2731                     handlers = (EventHandler)Delegate.Combine(handlers, value);
    2732                 }
    2733                 else
    2734                 {
    2735                     handlers = value;
    2736                 }
    2737                 // Set the delegate as an uncommon field
    2738                 InheritanceContextChangedHandlersField.SetValue(this, handlers);
    2739             }
    2740  
    2741             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2742             remove
    2743             {
    2744                 // Get existing event hanlders
    2745                 EventHandler handlers = InheritanceContextChangedHandlersField.GetValue(this);
    2746                 if (handlers != null)
    2747                 {
    2748                     // Remove the given handler
    2749                     handlers = (EventHandler)Delegate.Remove(handlers, value);
    2750                     if (handlers == null)
    2751                     {
    2752                         // Clear the value for the uncommon field
    2753                         // cause there are no more handlers
    2754                         InheritanceContextChangedHandlersField.ClearValue(this);
    2755                     }
    2756                     else
    2757                     {
    2758                         // Set the remaining handlers as an uncommon field
    2759                         InheritanceContextChangedHandlersField.SetValue(this, handlers);
    2760                     }
    2761                 }
    2762             }
    2763         }
    2764  
    2765         /// <summary>
    2766         ///     By default this is false since it doesn't have a context
    2767         /// </summary>
    2768         internal virtual bool HasMultipleInheritanceContexts
    2769         {
    2770             get { return false; }
    2771         }
    2772  
    2773         /// <summary>
    2774         ///     By default this is true since every DependencyObject can be an InheritanceContext
    2775         /// </summary>
    2776         internal bool CanBeInheritanceContext
    2777         {
    2778             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2779             get { return (_packedData & 0x00200000) != 0; }
    2780  
    2781             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2782             set
    2783             {
    2784                 if (value)
    2785                 {
    2786                     _packedData |= 0x00200000;
    2787                 }
    2788                 else
    2789                 {
    2790                     _packedData &= 0xFFDFFFFF;
    2791                 }
    2792             }
    2793         }
    2794  
    2795         [FriendAccessAllowed] // Built into Base, also used by Framework.
    2796         internal static bool IsTreeWalkOperation(OperationType operation)
    2797         {
    2798             return   operation == OperationType.AddChild ||
    2799                      operation == OperationType.RemoveChild ||
    2800                      operation == OperationType.Inherit;
    2801         }
    2802  
    2803         /// <summary>
    2804         /// Debug-only method that asserts that the current DO does not have any
    2805         /// listeners on its InheritanceContextChanged event. This is used by
    2806         /// Freezable (frozen Freezables can't have listeners).
    2807         /// </summary>
    2808         [Conditional ("DEBUG")]
    2809         internal void Debug_AssertNoInheritanceContextListeners()
    2810         {
    2811             Debug.Assert(InheritanceContextChangedHandlersField.GetValue(this) == null,
    2812                 "This object should not have any listeners to its InheritanceContextChanged event");
    2813         }
    2814  
    2815         // This uncommon field is used to store the handlers for the InheritanceContextChanged event
    2816         private  static readonly UncommonField<EventHandler> InheritanceContextChangedHandlersField = new UncommonField<EventHandler>();
    2817  
    2818         #endregion InheritanceContext
    2819  
    2820         #region EffectiveValues
    2821  
    2822         // The rest of DependencyObject is its EffectiveValues cache
    2823  
    2824         // The cache of effective (aka "computed" aka "resolved") property
    2825         // values for this DO.  If a DP does not have an entry in this array
    2826         // it means one of two things:
    2827         //  1) if it's an inheritable property, then its value may come from
    2828         //     this DO's InheritanceParent
    2829         //  2) if it's not an inheritable property (or this DO's InheritanceParent
    2830         //     doesn't have an entry for this DP either), then the value for
    2831         //     that DP on this DO is the default value.
    2832         // Otherwise, the DP will have an entry in this array describing the
    2833         // current value of the DP, where this value came from, and how it
    2834         // has been modified
    2835         internal EffectiveValueEntry[] EffectiveValues
    2836         {
    2837             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2838             get { return _effectiveValues; }
    2839         }
    2840  
    2841         // The total number of entries in the above EffectiveValues cache
    2842         internal uint EffectiveValuesCount
    2843         {
    2844             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2845             get { return _packedData & 0x000003FF; }
    2846             private set { _packedData = (_packedData & 0xFFFFFC00) | (value & 0x000003FF); }
    2847         }
    2848  
    2849         // The number of entries in the above EffectiveValues cache that
    2850         // correspond to DPs that are inheritable on this DO; this count
    2851         // helps us during "tree change" invalidations to know how big
    2852         // of a "working change list" we have to construct.
    2853         internal uint InheritableEffectiveValuesCount
    2854         {
    2855             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2856             get { return (_packedData >> 10) & 0x1FF; }
    2857             set
    2858             {
    2859                 Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    2860                 _packedData = ((value & 0x1FF) << 10) | (_packedData & 0xFFF803FF);
    2861             }
    2862         }
    2863  
    2864         // This flag indicates whether or not we are in "Property Initialization
    2865         // Mode".  This is an opt-in mode: a DO starts out *not* in Property
    2866         // Initialization Mode.  In this mode, the EffectiveValues cache grows
    2867         // at a more liberal (2.0) rate.  Normally, outside of this mode, the
    2868         // cache grows at a much stingier (1.2) rate.
    2869         // Internal customers (currently only UIElement) access this mode
    2870         // through the BeginPropertyInitialization/EndPropertyInitialization
    2871         // methods below
    2872         private bool IsInPropertyInitialization
    2873         {
    2874             get { return (_packedData & 0x00800000) != 0; }
    2875             set
    2876             {
    2877                 if (value)
    2878                 {
    2879                     _packedData |= 0x00800000;
    2880                 }
    2881                 else
    2882                 {
    2883                     _packedData &= 0xFF7FFFFF;
    2884                 }
    2885             }
    2886         }
    2887  
    2888         // A DependencyObject calls this method to indicate to the property
    2889         // system that a bunch of property sets are about to happen; the
    2890         // property system responds by elevating the growth rate of the
    2891         // EffectiveValues cache, to speed up initialization by requiring
    2892         // fewer reallocations
    2893         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
    2894         internal void BeginPropertyInitialization()
    2895         {
    2896             IsInPropertyInitialization = true;
    2897         }
    2898  
    2899         // A DependencyObject calls this method to indicate to the property
    2900         // system that it is now done with the bunch of property sets that
    2901         // accompanied the initialization of this element; the property
    2902         // system responds by returning the growth rate of the
    2903         // EffectiveValues cache to its normal rate, and then trimming
    2904         // the cache to get rid of any excess bloat incurred by the
    2905         // aggressive growth rate during initialization mode.
    2906         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
    2907         internal void EndPropertyInitialization()
    2908         {
    2909             IsInPropertyInitialization = false;
    2910  
    2911             if (_effectiveValues != null)
    2912             {
    2913                 uint effectiveValuesCount = EffectiveValuesCount;
    2914                 if (effectiveValuesCount != 0)
    2915                 {
    2916                     uint endLength = effectiveValuesCount;
    2917                     if (((float) endLength / (float) _effectiveValues.Length) < 0.8)
    2918                     {
    2919                         // For thread-safety, sealed DOs can't modify _effectiveValues.
    2920                         Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    2921  
    2922                         EffectiveValueEntry[] destEntries = new EffectiveValueEntry[endLength];
    2923                         Array.Copy(_effectiveValues, 0, destEntries, 0, effectiveValuesCount);
    2924                         _effectiveValues = destEntries;
    2925                     }
    2926                 }
    2927             }
    2928         }
    2929  
    2930  
    2931         internal DependencyObject InheritanceParent
    2932         {
    2933             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2934             get
    2935             {
    2936                 if ((_packedData & 0x3E100000) == 0)
    2937                 {
    2938                     return (DependencyObject) _contextStorage;
    2939                 }
    2940  
    2941                 // return null if this DO has any of the following set:
    2942                 //    IsSelfInheritanceParent
    2943                 //    Freezable_HasMultipleInheritanceContexts
    2944                 //    Freezable_UsingHandlerList
    2945                 //    Freezable_UsingContextList
    2946                 //    Freezable_UsingSingletonHandler
    2947                 //    Freezable_UsingSingletonContext
    2948                 return null;
    2949             }
    2950         }
    2951  
    2952         private void SetInheritanceParent(DependencyObject newParent)
    2953         {
    2954             Debug.Assert((_packedData & 0x3E000000) == 0, "InheritanceParent should not be set in a Freezable, which manages its own inheritance context.");
    2955  
    2956             // For thread-safety, sealed DOs can't modify _contextStorage
    2957             Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    2958  
    2959             if (_contextStorage != null)
    2960             {
    2961                 Debug.Assert(!IsSelfInheritanceParent, "If the IsSelfInheritanceParent is set then the InheritanceParent should have been ----d.");
    2962  
    2963                 _contextStorage = newParent;
    2964             }
    2965             else
    2966             {
    2967                 if (newParent != null)
    2968                 {
    2969                     // Merge all the inheritable properties on the inheritanceParent into the EffectiveValues
    2970                     // store on the current node because someone had set an effective value for an
    2971                     // inheritable property on this node.
    2972                     if (IsSelfInheritanceParent)
    2973                     {
    2974                         MergeInheritableProperties(newParent);
    2975                     }
    2976                     else
    2977                     {
    2978                         _contextStorage = newParent;
    2979                     }
    2980                 }
    2981                 else
    2982                 {
    2983                     // Do nothing because before and after values are both null
    2984                 }
    2985             }
    2986         }
    2987  
    2988  
    2989  
    2990         internal bool IsSelfInheritanceParent
    2991         {
    2992             [FriendAccessAllowed] // Built into Base, also used by Framework.
    2993             get { return (_packedData & 0x00100000) != 0; }
    2994         }
    2995  
    2996         // Currently we only have support for turning this flag on. Once set this flag never goes false after that.
    2997         [FriendAccessAllowed] // Built into Base, also used by Framework.
    2998         internal void SetIsSelfInheritanceParent()
    2999         {
    3000             // Merge all the inheritable properties on the inheritanceParent into the EffectiveValues
    3001             // store on the current node because someone tried to set an effective value for an
    3002             // inheritable property on this node.
    3003             DependencyObject inheritanceParent = InheritanceParent;
    3004             if (inheritanceParent != null)
    3005             {
    3006                 MergeInheritableProperties(inheritanceParent);
    3007  
    3008                 // Get rid of the InheritanceParent since we won't need it anymore for
    3009                 // having cached all the inheritable properties on self
    3010                 SetInheritanceParent(null);
    3011             }
    3012  
    3013             Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    3014  
    3015             _packedData |= 0x00100000;
    3016         }
    3017  
    3018         //
    3019         //  This method
    3020         //  1. Recalculates the InheritanceParent with respect to the given FrameworkParent
    3021         //  2. Is called from [FE/FCE].OnAncestorChangedInternal
    3022         //
    3023         [FriendAccessAllowed] // Built into Base, also used by Framework.
    3024         internal void SynchronizeInheritanceParent(DependencyObject parent)
    3025         {
    3026             // If this flag is true it indicates that all the inheritable properties for this node
    3027             // are cached on itself and hence we will not need the InheritanceParent pointer at all.
    3028             if (!this.IsSelfInheritanceParent)
    3029             {
    3030                 if (parent != null)
    3031                 {
    3032                     if (!parent.IsSelfInheritanceParent)
    3033                     {
    3034                         SetInheritanceParent(parent.InheritanceParent);
    3035                     }
    3036                     else
    3037                     {
    3038                         SetInheritanceParent(parent);
    3039                     }
    3040                 }
    3041                 else
    3042                 {
    3043                     SetInheritanceParent(null);
    3044                 }
    3045             }
    3046         }
    3047  
    3048         //
    3049         //  This method
    3050         //  1. Merges the inheritable properties from the parent into the EffectiveValues store on self
    3051         //
    3052         private void MergeInheritableProperties(DependencyObject inheritanceParent)
    3053         {
    3054             Debug.Assert(inheritanceParent != null, "Must have inheritanceParent");
    3055             Debug.Assert(inheritanceParent.IsSelfInheritanceParent, "An inheritanceParent should always be one that has all the inheritable properties cached on self");
    3056  
    3057             EffectiveValueEntry[] parentEffectiveValues = inheritanceParent.EffectiveValues;
    3058             uint parentEffectiveValuesCount = inheritanceParent.EffectiveValuesCount;
    3059  
    3060             for (uint i=0; i<parentEffectiveValuesCount; i++)
    3061             {
    3062                 EffectiveValueEntry entry = parentEffectiveValues[i];
    3063                 DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[entry.PropertyIndex];
    3064  
    3065                 // There are UncommonFields also stored in the EffectiveValues cache. We need to exclude those.
    3066                 if (dp != null)
    3067                 {
    3068                     PropertyMetadata metadata = dp.GetMetadata(DependencyObjectType);
    3069                     if (metadata.IsInherited)
    3070                     {
    3071                         object value = inheritanceParent.GetValueEntry(
    3072                                             new EntryIndex(i),
    3073                                             dp,
    3074                                             metadata,
    3075                                             RequestFlags.SkipDefault | RequestFlags.DeferredReferences).Value;
    3076                         if (value != DependencyProperty.UnsetValue)
    3077                         {
    3078                             EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);
    3079  
    3080                             SetEffectiveValue(entryIndex, dp, dp.GlobalIndex, metadata, value, BaseValueSourceInternal.Inherited);
    3081                         }
    3082                     }
    3083                 }
    3084             }
    3085         }
    3086  
    3087         //
    3088         //  This method
    3089         //  1. Is used to check if the given entryIndex needs any change. It
    3090         //  could happen that we have made a call out and thereby caused changes
    3091         //  to the _effectiveValues store on the current element. In that case
    3092         //  we would need to aquire new value for the index.
    3093         //
    3094         private EntryIndex CheckEntryIndex(EntryIndex entryIndex, int targetIndex)
    3095         {
    3096             uint effectiveValuesCount = EffectiveValuesCount;
    3097             if (effectiveValuesCount > 0 && _effectiveValues.Length > entryIndex.Index)
    3098             {
    3099                 EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
    3100                 if (entry.PropertyIndex == targetIndex)
    3101                 {
    3102                     return new EntryIndex(entryIndex.Index);
    3103                 }
    3104             }
    3105  
    3106             return LookupEntry(targetIndex);
    3107         }
    3108  
    3109         // look for an entry that matches the given dp
    3110         // return value has Found set to true if an entry is found
    3111         // return value has Index set to the index of the found entry (if Found is true)
    3112         //            or  the location to insert an entry for this dp (if Found is false)
    3113         [FriendAccessAllowed] // Built into Base, also used by Framework.
    3114         internal EntryIndex LookupEntry(int targetIndex)
    3115         {
    3116             int checkIndex;
    3117             uint iLo = 0;
    3118             uint iHi = EffectiveValuesCount;
    3119  
    3120             if (iHi <= 0)
    3121             {
    3122                 return new EntryIndex(0, false /* Found */);
    3123             }
    3124  
    3125             // Do a binary search to find the value
    3126             while (iHi - iLo > 3)
    3127             {
    3128                 uint iPv = (iHi + iLo) / 2;
    3129                 checkIndex = _effectiveValues[iPv].PropertyIndex;
    3130                 if (targetIndex == checkIndex)
    3131                 {
    3132                     return new EntryIndex(iPv);
    3133                 }
    3134                 if (targetIndex <= checkIndex)
    3135                 {
    3136                     iHi = iPv;
    3137                 }
    3138                 else
    3139                 {
    3140                     iLo = iPv + 1;
    3141                 }
    3142             }
    3143  
    3144             // Now we only have three values to search; switch to a linear search
    3145             do
    3146             {
    3147                 checkIndex = _effectiveValues[iLo].PropertyIndex;
    3148  
    3149                 if (checkIndex == targetIndex)
    3150                 {
    3151                     return new EntryIndex(iLo);
    3152                 }
    3153  
    3154                 if (checkIndex > targetIndex)
    3155                 {
    3156                     // we've gone past the targetIndex - return not found
    3157                     break;
    3158                 }
    3159  
    3160                 iLo++;
    3161             }
    3162             while (iLo < iHi);
    3163  
    3164             return new EntryIndex(iLo, false /* Found */);
    3165         }
    3166  
    3167         // insert the given entry at the given index
    3168         // this function assumes that entryIndex is at the right
    3169         // location such that the resulting list remains sorted by EffectiveValueEntry.PropertyIndex
    3170         private void InsertEntry(EffectiveValueEntry entry, uint entryIndex)
    3171         {
    3172             // For thread-safety, sealed DOs can't modify _effectiveValues.
    3173             Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    3174  
    3175 #if DEBUG
    3176             EntryIndex debugIndex = LookupEntry(entry.PropertyIndex);
    3177             Debug.Assert(!debugIndex.Found && debugIndex.Index == entryIndex, "Inserting duplicate");
    3178 #endif
    3179  
    3180             if (CanModifyEffectiveValues == false)
    3181             {
    3182                 throw new InvalidOperationException(SR.Get(SRID.LocalValueEnumerationInvalidated));
    3183             }
    3184  
    3185             uint effectiveValuesCount = EffectiveValuesCount;
    3186             if (effectiveValuesCount > 0)
    3187             {
    3188                 if (_effectiveValues.Length == effectiveValuesCount)
    3189                 {
    3190                     int newSize = (int) (effectiveValuesCount * (IsInPropertyInitialization ? 2.0 : 1.2));
    3191                     if (newSize == effectiveValuesCount)
    3192                     {
    3193                         newSize++;
    3194                     }
    3195  
    3196                     EffectiveValueEntry[] destEntries = new EffectiveValueEntry[newSize];
    3197                     Array.Copy(_effectiveValues, 0, destEntries, 0, entryIndex);
    3198                     destEntries[entryIndex] = entry;
    3199                     Array.Copy(_effectiveValues, entryIndex, destEntries, entryIndex + 1, effectiveValuesCount - entryIndex);
    3200                     _effectiveValues = destEntries;
    3201                 }
    3202                 else
    3203                 {
    3204                     Array.Copy(_effectiveValues, entryIndex, _effectiveValues, entryIndex + 1, effectiveValuesCount - entryIndex);
    3205                     _effectiveValues[entryIndex] = entry;
    3206                 }
    3207             }
    3208             else
    3209             {
    3210                 if (_effectiveValues == null)
    3211                 {
    3212                     _effectiveValues = new EffectiveValueEntry[EffectiveValuesInitialSize];
    3213                 }
    3214                 _effectiveValues[0] = entry;
    3215             }
    3216             EffectiveValuesCount = effectiveValuesCount + 1;
    3217         }
    3218  
    3219         // remove the entry at the given index
    3220         private void RemoveEntry(uint entryIndex, DependencyProperty dp)
    3221         {
    3222             // For thread-safety, sealed DOs can't modify _effectiveValues.
    3223             Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    3224  
    3225             if (CanModifyEffectiveValues == false)
    3226             {
    3227                 throw new InvalidOperationException(SR.Get(SRID.LocalValueEnumerationInvalidated));
    3228             }
    3229  
    3230             uint effectiveValuesCount = EffectiveValuesCount;
    3231             Array.Copy(_effectiveValues, entryIndex + 1, _effectiveValues, entryIndex, (effectiveValuesCount - entryIndex) - 1);
    3232             effectiveValuesCount--;
    3233             EffectiveValuesCount = effectiveValuesCount;
    3234  
    3235             // clear last entry
    3236             _effectiveValues[effectiveValuesCount].Clear();
    3237         }
    3238  
    3239         //
    3240         //  This property
    3241         //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
    3242         //  2. This is a performance optimization
    3243         //
    3244         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
    3245         internal virtual int EffectiveValuesInitialSize
    3246         {
    3247             get { return 2; }
    3248         }
    3249  
    3250         internal void SetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry newEntry, EffectiveValueEntry oldEntry)
    3251         {
    3252             if (metadata != null &&
    3253                 metadata.IsInherited &&
    3254                 (newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Inherited ||
    3255                     newEntry.IsCoerced || newEntry.IsAnimated) &&
    3256                 !IsSelfInheritanceParent)
    3257             {
    3258                 SetIsSelfInheritanceParent();
    3259                 entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
    3260             }
    3261  
    3262             bool restoreMarker = false;
    3263  
    3264             if (oldEntry.HasExpressionMarker && !newEntry.HasExpressionMarker)
    3265             {
    3266                 BaseValueSourceInternal valueSource = newEntry.BaseValueSourceInternal;
    3267                 restoreMarker = (valueSource == BaseValueSourceInternal.ThemeStyle ||
    3268                                  valueSource == BaseValueSourceInternal.ThemeStyleTrigger ||
    3269                                  valueSource == BaseValueSourceInternal.Style ||
    3270                                  valueSource == BaseValueSourceInternal.TemplateTrigger ||
    3271                                  valueSource == BaseValueSourceInternal.StyleTrigger ||
    3272                                  valueSource == BaseValueSourceInternal.ParentTemplate ||
    3273                                  valueSource == BaseValueSourceInternal.ParentTemplateTrigger);
    3274             }
    3275  
    3276             if (restoreMarker)
    3277             {
    3278                 newEntry.RestoreExpressionMarker();
    3279             }
    3280             else if (oldEntry.IsExpression && oldEntry.ModifiedValue.ExpressionValue == Expression.NoValue)
    3281             {
    3282                 // we now have a value for an expression that is "hiding" - save it
    3283                 // as the expression value
    3284                 newEntry.SetExpressionValue(newEntry.Value, oldEntry.ModifiedValue.BaseValue);
    3285             }
    3286  
    3287 #if DEBUG
    3288             object baseValue;
    3289             if (!newEntry.HasModifiers)
    3290             {
    3291                 baseValue = newEntry.Value;
    3292             }
    3293             else
    3294             {
    3295                 if (newEntry.IsCoercedWithCurrentValue)
    3296                 {
    3297                     baseValue = newEntry.ModifiedValue.CoercedValue;
    3298                 }
    3299                 else if (newEntry.IsExpression)
    3300                 {
    3301                     baseValue = newEntry.ModifiedValue.ExpressionValue;
    3302                 }
    3303                 else
    3304                 {
    3305                     baseValue = newEntry.ModifiedValue.BaseValue;
    3306                 }
    3307             }
    3308  
    3309             Debug.Assert(newEntry.IsDeferredReference == (baseValue is DeferredReference));
    3310 #endif
    3311  
    3312             if (entryIndex.Found)
    3313             {
    3314                 _effectiveValues[entryIndex.Index] = newEntry;
    3315             }
    3316             else
    3317             {
    3318                 InsertEntry(newEntry, entryIndex.Index);
    3319                 if (metadata != null && metadata.IsInherited)
    3320                 {
    3321                     InheritableEffectiveValuesCount++;
    3322                 }
    3323             }
    3324  
    3325             Debug.Assert(dp == null || (dp.GlobalIndex == newEntry.PropertyIndex), "EffectiveValueEntry & DependencyProperty do not match");
    3326         }
    3327  
    3328         //
    3329         //  This method
    3330         //  1. Create a new EffectiveValueEntry for the given DP and inserts it into the EffectiveValues list
    3331         //
    3332         [FriendAccessAllowed] // Built into Base, also used by Core and Framework.
    3333         internal void SetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, int targetIndex, PropertyMetadata metadata, object value, BaseValueSourceInternal valueSource)
    3334         {
    3335             Debug.Assert(value != DependencyProperty.UnsetValue, "Value to be set cannot be UnsetValue");
    3336             Debug.Assert(valueSource != BaseValueSourceInternal.Unknown, "ValueSource cannot be Unknown");
    3337  
    3338             // For thread-safety, sealed DOs can't modify _effectiveValues.
    3339             Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    3340  
    3341             if (metadata != null &&
    3342                 metadata.IsInherited &&
    3343                 valueSource != BaseValueSourceInternal.Inherited &&
    3344                 !IsSelfInheritanceParent)
    3345             {
    3346                 SetIsSelfInheritanceParent();
    3347                 entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
    3348             }
    3349  
    3350             EffectiveValueEntry entry;
    3351             if (entryIndex.Found)
    3352             {
    3353                 entry = _effectiveValues[entryIndex.Index];
    3354             }
    3355             else
    3356             {
    3357                 entry = new EffectiveValueEntry();
    3358                 entry.PropertyIndex = targetIndex;
    3359                 InsertEntry(entry, entryIndex.Index);
    3360                 if (metadata != null && metadata.IsInherited)
    3361                 {
    3362                     InheritableEffectiveValuesCount++;
    3363                 }
    3364             }
    3365  
    3366             bool hasExpressionMarker = (value == ExpressionInAlternativeStore);
    3367  
    3368             if (!hasExpressionMarker &&
    3369                 entry.HasExpressionMarker &&
    3370                 (valueSource == BaseValueSourceInternal.ThemeStyle ||
    3371                  valueSource == BaseValueSourceInternal.ThemeStyleTrigger ||
    3372                  valueSource == BaseValueSourceInternal.Style ||
    3373                  valueSource == BaseValueSourceInternal.TemplateTrigger ||
    3374                  valueSource == BaseValueSourceInternal.StyleTrigger ||
    3375                  valueSource == BaseValueSourceInternal.ParentTemplate ||
    3376                  valueSource == BaseValueSourceInternal.ParentTemplateTrigger))
    3377             {
    3378                 entry.BaseValueSourceInternal = valueSource;
    3379                 entry.SetExpressionValue(value, ExpressionInAlternativeStore);
    3380                 entry.ResetAnimatedValue();
    3381                 entry.ResetCoercedValue();
    3382             }
    3383             else if (entry.IsExpression && entry.ModifiedValue.ExpressionValue == Expression.NoValue)
    3384             {
    3385                 // we now have a value for an expression that is "hiding" - save it
    3386                 // as the expression value
    3387                 entry.SetExpressionValue(value, entry.ModifiedValue.BaseValue);
    3388             }
    3389             else
    3390             {
    3391                 Debug.Assert(entry.BaseValueSourceInternal != BaseValueSourceInternal.Local || valueSource == BaseValueSourceInternal.Local,
    3392                     "No one but another local value can stomp over an existing local value. The only way is to clear the entry");
    3393  
    3394                 entry.BaseValueSourceInternal = valueSource;
    3395                 entry.ResetValue(value, hasExpressionMarker);
    3396             }
    3397  
    3398             Debug.Assert(dp == null || (dp.GlobalIndex == entry.PropertyIndex), "EffectiveValueEntry & DependencyProperty do not match");
    3399             _effectiveValues[entryIndex.Index] = entry;
    3400         }
    3401  
    3402  
    3403         //
    3404         //  This method
    3405         //  1. Removes the entry if there is one with valueSource >= the specified
    3406         //
    3407         internal void UnsetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata)
    3408         {
    3409             if (entryIndex.Found)
    3410             {
    3411                 RemoveEntry(entryIndex.Index, dp);
    3412                 if (metadata != null && metadata.IsInherited)
    3413                 {
    3414                     InheritableEffectiveValuesCount--;
    3415                 }
    3416             }
    3417         }
    3418  
    3419         //
    3420         //  This method
    3421         //  1. Sets the expression on a ModifiedValue entry
    3422         //
    3423         private void SetExpressionValue(EntryIndex entryIndex, object value, object baseValue)
    3424         {
    3425             Debug.Assert(value != DependencyProperty.UnsetValue, "Value to be set cannot be UnsetValue");
    3426             Debug.Assert(baseValue != DependencyProperty.UnsetValue, "BaseValue to be set cannot be UnsetValue");
    3427             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.");
    3428  
    3429             // For thread-safety, sealed DOs can't modify _effectiveValues.
    3430             Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified");
    3431  
    3432             EffectiveValueEntry entry = _effectiveValues[entryIndex.Index];
    3433  
    3434             entry.SetExpressionValue(value, baseValue);
    3435             entry.ResetAnimatedValue();
    3436             entry.ResetCoercedValue();
    3437             _effectiveValues[entryIndex.Index] = entry;
    3438         }
    3439  
    3440         /// <summary>
    3441         ///     Helper method to compare two DP values
    3442         /// </summary>
    3443         private bool Equals(DependencyProperty dp, object value1, object value2)
    3444         {
    3445             if (dp.IsValueType || dp.IsStringType)
    3446             {
    3447                 // Use Object.Equals for Strings and ValueTypes
    3448                 return Object.Equals(value1, value2);
    3449             }
    3450             else
    3451             {
    3452                 // Use Object.ReferenceEquals for all other ReferenceTypes
    3453                 return Object.ReferenceEquals(value1, value2);
    3454             }
    3455         }
    3456  
    3457         #endregion EffectiveValues
    3458  
    3459         #region InstanceData
    3460  
    3461         // Specialized Type identification
    3462         private DependencyObjectType _dType;
    3463  
    3464         // For Freezable:
    3465         //    To save working set this object will initially reference a
    3466         //    single delegate/context.  If a second object is added
    3467         //    of the same type, we will convert to a list/list, which will
    3468         //    be stored in _contextStorage.  If the user ever adds an object of the
    3469         //    other type, we will create a HandlerContextStorage class, which _contextStorage
    3470         //    will then point at.
    3471  
    3472         // For FrameworkContentElement/FrameworkElement:
    3473         //    This is the parent whose effective values store would contain the
    3474         //    value for the inheritable property on you. This change part of the
    3475         //    performance optimization around inheritable properties whereby you
    3476         //    wouldn't store the inheritable property on each and every node but
    3477         //    will hold it only the node that the property was actually set.
    3478         internal object _contextStorage;
    3479  
    3480         // The cache of effective values for this DependencyObject
    3481         // This is an array sorted by DP.GlobalIndex.  This ordering is
    3482         // maintained via an insertion sort algorithm.
    3483         private EffectiveValueEntry[] _effectiveValues;
    3484  
    3485         // Stores:
    3486         // Bits  0- 9 (0x000003FF): EffectiveValuesCount (0-1023)
    3487         // Bits 10-18 (0x0007FC00): InheritableEffectiveValuesCount (0-511)
    3488         //     Bit 19 (0x00080000): CanModifyEffectiveValues, says if you can change the _effectiveValues cache on the current element.
    3489         //     Bit 20 (0x00100000): IsSelfInheritanceParent, says if all your inheritable property values are built into your effectiveValues store
    3490         //     Bit 21 (0x00200000): CanBeInheritanceContext, says if you can be an InheritanceContext for someone
    3491         //     Bit 22 (0x00400000): IsSealed:  whether or not this DO is in readonly mode
    3492         //     Bit 23 (0x00800000): PropertyInitialization mode
    3493         //     Bit 24 (0x01000000): IsInheritanceContextSealed, says if you can change InheritanceContext
    3494         //     Bit 25 (0x02000000): Freezable_HasMultipleInheritanceContexts
    3495         //     Bit 26 (0x04000000): Freezable_UsingHandlerList
    3496         //     Bit 27 (0x08000000): Freezable_UsingContextList
    3497         //     Bit 28 (0x10000000): Freezable_UsingSingletonHandler
    3498         //     Bit 29 (0x20000000): Freezable_UsingSingletonContext
    3499         //     Bit 30 (0x40000000): Animatable_IsResourceInvalidationNecessary
    3500         //     Bit 31 (0x80000000): Animatable_HasAnimatedProperties
    3501  
    3502         private UInt32 _packedData = 0;
    3503  
    3504         #endregion InstanceData
    3505  
    3506         #region StaticData
    3507  
    3508         // special value in local store meaning that some alternative store (e.g.
    3509         // the Framework's per-instance StyleData) is holding an Expression to
    3510         // which we want to delegate SetValue.
    3511         [FriendAccessAllowed] // Built into Base, also used by Framework.
    3512         internal static readonly object ExpressionInAlternativeStore = new NamedObject("ExpressionInAlternativeStore");
    3513  
    3514         // callbacks used for alternative expression storage
    3515         private static AlternativeExpressionStorageCallback _getExpressionCore;
    3516  
    3517 #if VERBOSE_PROPERTY_EVENT
    3518         internal static int ValidationCount;
    3519         internal static int InvalidationCount;
    3520 #endif
    3521  
    3522         // This field stores the list of dependents in a FrugalMap.
    3523         // The field is of type object for two reasons:
    3524         // 1) FrugalMap is a struct, and generics over value types have perf issues
    3525         // 2) so that we can have the default value of "null" mean Unset.
    3526         internal static readonly UncommonField<object> DependentListMapField = new UncommonField<object>();
    3527  
    3528         // Optimization, to avoid calling FromSystemType too often
    3529         internal static DependencyObjectType DType = DependencyObjectType.FromSystemTypeInternal(typeof(DependencyObject));
    3530  
    3531         private const int NestedOperationMaximum = 153;
    3532  
    3533         #endregion StaticData
    3534    }
    3535  
    3536     /// <summary> Callback used by the "alternative Expression storage" feature </summary>
    3537     /// <remarks>
    3538     /// This should only be used by the Framework.  It should not be used directly by users.
    3539     /// </remarks>
    3540     [FriendAccessAllowed] // Built into Base, also used by Framework.
    3541     internal delegate Expression AlternativeExpressionStorageCallback(DependencyObject d, DependencyProperty dp, PropertyMetadata metadata);
    3542  
    3543     [FriendAccessAllowed] // Built into Base, also used by Framework.
    3544     internal enum UpdateResult
    3545     {
    3546         ValueChanged = 0x01,
    3547         NotificationSent = 0x02,
    3548         InheritedValueOverridden = 0x04,
    3549     }
    3550  
    3551     [FriendAccessAllowed] // Built into Base, also used by Framework.
    3552     internal enum RequestFlags
    3553     {
    3554         FullyResolved = 0x00,
    3555         AnimationBaseValue = 0x01,
    3556         CoercionBaseValue = 0x02,
    3557         DeferredReferences = 0x04,
    3558         SkipDefault = 0x08,
    3559         RawEntry = 0x10,
    3560     }
    3561 }
  • 相关阅读:
    格子地图生成导航网格
    Geometry Shader 实现 Wireframe 绘制边线的Shader
    体素爆炸
    弹孔,血迹 等受击表现
    Behaviac 腾讯开源行为树 简介(给策划)
    unable to unroll loop 报错
    Unity编辑器扩展
    追踪弹路径
    代码管理资源属性
    主机排行网重大更新,移动端自适应
  • 原文地址:https://www.cnblogs.com/yuanchenhui/p/DependencyObject.html
Copyright © 2020-2023  润新知