// Token: 0x06000C66 RID: 3174 RVA: 0x0002E490 File Offset: 0x0002C690 private static bool InvalidateTreeDependentProperty(TreeChangeInfo info, DependencyObject d, ref FrameworkObject fo, DependencyProperty dp, FrameworkPropertyMetadata fMetadata, Style selfStyle, Style selfThemeStyle, ref ChildRecord childRecord, bool isChildRecordValid, bool hasStyleChanged, bool isSelfInheritanceParent, bool wasSelfInheritanceParent) { if (!TreeWalkHelper.SkipNext(fo.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { InheritablePropertyChangeInfo rootInheritableValue = info.GetRootInheritableValue(dp); EffectiveValueEntry oldEntry = rootInheritableValue.OldEntry; EffectiveValueEntry effectiveValueEntry = info.IsAddOperation ? rootInheritableValue.NewEntry : new EffectiveValueEntry(dp, BaseValueSourceInternal.Inherited); bool flag = TreeWalkHelper.IsForceInheritedProperty(dp); if (d != info.Root) { if (wasSelfInheritanceParent) { oldEntry = d.GetValueEntry(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); } else if (isSelfInheritanceParent) { EffectiveValueEntry valueEntry = d.GetValueEntry(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); if (valueEntry.BaseValueSourceInternal <= BaseValueSourceInternal.Inherited) { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } else { oldEntry = valueEntry; } } else { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } else if (info.IsAddOperation && (flag || oldEntry.BaseValueSourceInternal <= BaseValueSourceInternal.Inherited)) { EffectiveValueEntry valueEntry2 = d.GetValueEntry(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); if (valueEntry2.BaseValueSourceInternal > BaseValueSourceInternal.Inherited) { oldEntry = valueEntry2; } } OperationType operationType = info.IsAddOperation ? OperationType.AddChild : OperationType.RemoveChild; if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { return((d.UpdateEffectiveValue(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref effectiveValueEntry, false, false, operationType) & (UpdateResult)5) == UpdateResult.ValueChanged); } if (flag) { effectiveValueEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); return((d.UpdateEffectiveValue(d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref effectiveValueEntry, false, false, operationType) & (UpdateResult)5) == UpdateResult.ValueChanged); } } return(false); }
// // This method // 1. Is called from AncestorChange InvalidateTree. // 2. It is used to create the InheritableProperties on the given node. // 3. It also accumulates oldValues for the inheritable properties that are about to be invalidated // internal FrugalObjectList<DependencyProperty> CreateParentInheritableProperties( DependencyObject d, DependencyObject parent, bool isAddOperation) { Debug.Assert(d != null, "Must have non-null current node"); if (parent == null) { return new FrugalObjectList<DependencyProperty>(0); } DependencyObjectType treeObjDOT = d.DependencyObjectType; // See if we have a cached value. EffectiveValueEntry[] parentEffectiveValues = null; uint parentEffectiveValuesCount = 0; uint inheritablePropertiesCount = 0; // If inheritable properties aren't cached on you then use the effective // values cache on the parent to discover those inherited properties that // may need to be invalidated on the children nodes. if (!parent.IsSelfInheritanceParent) { DependencyObject inheritanceParent = parent.InheritanceParent; if (inheritanceParent != null) { parentEffectiveValues = inheritanceParent.EffectiveValues; parentEffectiveValuesCount = inheritanceParent.EffectiveValuesCount; inheritablePropertiesCount = inheritanceParent.InheritableEffectiveValuesCount; } } else { parentEffectiveValues = parent.EffectiveValues; parentEffectiveValuesCount = parent.EffectiveValuesCount; inheritablePropertiesCount = parent.InheritableEffectiveValuesCount; } FrugalObjectList<DependencyProperty> inheritableProperties = new FrugalObjectList<DependencyProperty>((int) inheritablePropertiesCount); if (inheritablePropertiesCount == 0) { return inheritableProperties; } _rootInheritableValues = new InheritablePropertyChangeInfo[(int) inheritablePropertiesCount]; int inheritableIndex = 0; FrameworkObject foParent = new FrameworkObject(parent); for (uint i=0; i<parentEffectiveValuesCount; i++) { // Add all the inheritable properties from the effectiveValues // cache to the TreeStateCache on the parent EffectiveValueEntry entry = parentEffectiveValues[i]; DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[entry.PropertyIndex]; // There are UncommonFields also stored in the EffectiveValues cache. We need to exclude those. if ((dp != null) && dp.IsPotentiallyInherited) { PropertyMetadata metadata = dp.GetMetadata(parent.DependencyObjectType); if (metadata != null && metadata.IsInherited) { Debug.Assert(!inheritableProperties.Contains(dp), "EffectiveValues cache must not contains duplicate entries for the same DP"); FrameworkPropertyMetadata fMetadata = (FrameworkPropertyMetadata)metadata; // Children do not need to inherit properties across a tree boundary // unless the property is set to override this behavior. if (!TreeWalkHelper.SkipNow(foParent.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { inheritableProperties.Add(dp); EffectiveValueEntry oldEntry; EffectiveValueEntry newEntry; oldEntry = d.GetValueEntry( d.LookupEntry(dp.GlobalIndex), dp, dp.GetMetadata(treeObjDOT), RequestFlags.DeferredReferences); if (isAddOperation) { // set up the new value newEntry = entry; if ((newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Default) || newEntry.HasModifiers) { newEntry = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved); newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } else { newEntry = new EffectiveValueEntry(); } _rootInheritableValues[inheritableIndex++] = new InheritablePropertyChangeInfo(d, dp, oldEntry, newEntry); if (inheritablePropertiesCount == inheritableIndex) { // no more inheritable properties, bail early break; } } } } } return inheritableProperties; }
/// <summary> /// Callback on visiting each node in the descendency /// during an inheritable property change /// </summary> private static bool OnInheritablePropertyChanged( DependencyObject d, InheritablePropertyChangeInfo info) { Debug.Assert(d != null, "Must have non-null current node"); DependencyProperty dp = info.Property; EffectiveValueEntry oldEntry = info.OldEntry; EffectiveValueEntry newEntry = info.NewEntry; InheritanceBehavior inheritanceBehavior; bool inheritanceNode = IsInheritanceNode(d, dp, out inheritanceBehavior); bool isForceInheritedProperty = IsForceInheritedProperty(dp); // Note that if a node is marked SkipNext means it hasn't acquired any values from its parent and // hence we do not need to invalidate this node or any of its descendents. However if a node is // marked SkipNow then this node might have acquired values from its parent but none of its // descendents would. Hence in this case we process the current node but omit all of its descendents. if (inheritanceNode && (!SkipNext(inheritanceBehavior) || isForceInheritedProperty)) { PropertyMetadata metadata = dp.GetMetadata(d); EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex); // Found an inheritance node if (!d.IsSelfInheritanceParent) { DependencyObject parent = FrameworkElement.GetFrameworkParent(d); InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (parent != null) { FrameworkObject parentFO = new FrameworkObject(parent, true); parentInheritanceBehavior = parentFO.InheritanceBehavior; } if (!SkipNext(inheritanceBehavior) && !SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent d.SynchronizeInheritanceParent(parent); } // What should the oldValueSource on the child be? // When the oldValue on the parent was default it // means that the child also used its own default // and did not inherit from the parent. However // when the value on the parent was non-default // it means that the child inherited it. // Note that the oldValueSource on inheritablePropertyChangedData // is actually the parent's oldValueSource if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) { // we use an empty EffectiveValueEntry as a signal that the old entry was the default value oldEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(d, dp)); } } else { oldEntry = d.GetValueEntry( entryIndex, dp, metadata, RequestFlags.RawEntry); } // If the oldValueSource is of lower precedence than Inheritance // only then do we need to Invalidate the property if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { // Since we do not hold a cache of the oldValue we need to supply one // in order to correctly fire the change notification return (d.UpdateEffectiveValue( entryIndex, dp, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Inherit) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } else if (isForceInheritedProperty) { // IsCoerced == true && value == UnsetValue indicates that we need to re-coerce this value newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); // Re-coerce a force inherited property because it's coersion depends on treeness return (d.UpdateEffectiveValue( d.LookupEntry(dp.GlobalIndex), dp, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Inherit) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } else { return false; } } // Do not continue walk down subtree if the walk was forced to stop // (due to separated trees) return (inheritanceBehavior == InheritanceBehavior.Default || isForceInheritedProperty); }
/// <summary> /// Invalidate this property if /// - It is not locally set and /// - It is not acquired from a style/template /// </summary> private static bool InvalidateTreeDependentProperty( TreeChangeInfo info, DependencyObject d, ref FrameworkObject fo, DependencyProperty dp, FrameworkPropertyMetadata fMetadata, Style selfStyle, Style selfThemeStyle, ref ChildRecord childRecord, bool isChildRecordValid, bool hasStyleChanged, bool isSelfInheritanceParent) { Debug.Assert(d != null, "Must have non-null current node"); // This must be an inherited dependency property Debug.Assert(fMetadata.IsInherited == true, "This must be an inherited dependency property"); // Children do not need to inherit properties across a tree boundary // unless the property is set to override this behavior. if (!SkipNext(fo.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { InheritablePropertyChangeInfo rootInfo = info.GetRootInheritableValue(dp); EffectiveValueEntry oldEntry = rootInfo.OldEntry; EffectiveValueEntry newEntry = info.IsAddOperation ? rootInfo.NewEntry : new EffectiveValueEntry(dp, BaseValueSourceInternal.Inherited); bool isForceInheritedProperty = IsForceInheritedProperty(dp); if (d != info.Root) { if (isSelfInheritanceParent) { oldEntry = d.GetValueEntry( d.LookupEntry(dp.GlobalIndex), dp, fMetadata, RequestFlags.DeferredReferences); } else { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } OperationType operationType = info.IsAddOperation ? OperationType.AddChild : OperationType.RemoveChild; if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { // If the oldValueSource is of lower precedence than Inheritance // only then do we need to Invalidate the property. Examples of // values with higher precedence are those that are locally set // or set via a style/template. return (d.UpdateEffectiveValue( d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, operationType) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } else if (isForceInheritedProperty) { // IsCoerced == true && value == UnsetValue indicates that we need to re-coerce this value newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); // Re-coerce a force inherited property because it's coersion depends on treeness return (d.UpdateEffectiveValue( d.LookupEntry(dp.GlobalIndex), dp, fMetadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, operationType) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } } return false; }
// // This method // 1. Merges the inheritable properties from the parent into the EffectiveValues store on self // private void MergeInheritableProperties(DependencyObject inheritanceParent) { Debug.Assert(inheritanceParent != null, "Must have inheritanceParent"); Debug.Assert(inheritanceParent.IsSelfInheritanceParent, "An inheritanceParent should always be one that has all the inheritable properties cached on self"); EffectiveValueEntry[] parentEffectiveValues = inheritanceParent.EffectiveValues; uint parentEffectiveValuesCount = inheritanceParent.EffectiveValuesCount; for (uint i=0; i<parentEffectiveValuesCount; i++) { EffectiveValueEntry entry = parentEffectiveValues[i]; DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[entry.PropertyIndex]; // There are UncommonFields also stored in the EffectiveValues cache. We need to exclude those. if (dp != null) { PropertyMetadata metadata = dp.GetMetadata(DependencyObjectType); if (metadata.IsInherited) { object value = inheritanceParent.GetValueEntry( new EntryIndex(i), dp, metadata, RequestFlags.SkipDefault | RequestFlags.DeferredReferences).Value; if (value != DependencyProperty.UnsetValue) { EntryIndex entryIndex = LookupEntry(dp.GlobalIndex); SetEffectiveValue(entryIndex, dp, dp.GlobalIndex, metadata, value, BaseValueSourceInternal.Inherited); } } } } }
// Token: 0x06000C6D RID: 3181 RVA: 0x0002EB78 File Offset: 0x0002CD78 private static bool OnInheritablePropertyChanged(DependencyObject d, InheritablePropertyChangeInfo info, bool visitedViaVisualTree) { DependencyProperty property = info.Property; EffectiveValueEntry oldEntry = info.OldEntry; EffectiveValueEntry newEntry = info.NewEntry; InheritanceBehavior inheritanceBehavior; bool flag = TreeWalkHelper.IsInheritanceNode(d, property, out inheritanceBehavior); bool flag2 = TreeWalkHelper.IsForceInheritedProperty(property); if (!flag || (TreeWalkHelper.SkipNext(inheritanceBehavior) && !flag2)) { return(inheritanceBehavior == InheritanceBehavior.Default || flag2); } PropertyMetadata metadata = property.GetMetadata(d); EntryIndex entryIndex = d.LookupEntry(property.GlobalIndex); if (!d.IsSelfInheritanceParent) { DependencyObject frameworkParent = FrameworkElement.GetFrameworkParent(d); InheritanceBehavior inheritanceBehavior2 = InheritanceBehavior.Default; if (frameworkParent != null) { FrameworkObject frameworkObject = new FrameworkObject(frameworkParent, true); inheritanceBehavior2 = frameworkObject.InheritanceBehavior; } if (!TreeWalkHelper.SkipNext(inheritanceBehavior) && !TreeWalkHelper.SkipNow(inheritanceBehavior2)) { d.SynchronizeInheritanceParent(frameworkParent); } if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) { oldEntry = EffectiveValueEntry.CreateDefaultValueEntry(property, metadata.GetDefaultValue(d, property)); } } else { oldEntry = d.GetValueEntry(entryIndex, property, metadata, RequestFlags.RawEntry); } if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { if (visitedViaVisualTree && FrameworkElement.DType.IsInstanceOfType(d)) { DependencyObject parent = LogicalTreeHelper.GetParent(d); if (parent != null) { DependencyObject parent2 = VisualTreeHelper.GetParent(d); if (parent2 != null && parent2 != parent) { return(false); } } } return((d.UpdateEffectiveValue(entryIndex, property, metadata, oldEntry, ref newEntry, false, false, OperationType.Inherit) & (UpdateResult)5) == UpdateResult.ValueChanged); } if (flag2) { newEntry = new EffectiveValueEntry(property, FullValueSource.IsCoerced); return((d.UpdateEffectiveValue(d.LookupEntry(property.GlobalIndex), property, metadata, oldEntry, ref newEntry, false, false, OperationType.Inherit) & (UpdateResult)5) == UpdateResult.ValueChanged); } return(false); }
private static bool DefaultFreezeValueCallback( DependencyObject d, DependencyProperty dp, EntryIndex entryIndex, PropertyMetadata metadata, bool isChecking) { // The expression check only needs to be done when isChecking is true // because if we return false here the Freeze() call will fail. if (isChecking) { if (d.HasExpression(entryIndex, dp)) { if (TraceFreezable.IsEnabled) { TraceFreezable.Trace( TraceEventType.Warning, TraceFreezable.UnableToFreezeExpression, d, dp, dp.OwnerType); } return false; } } if (!dp.IsValueType) { object value = d.GetValueEntry( entryIndex, dp, metadata, RequestFlags.FullyResolved).Value; if (value != null) { Freezable valueAsFreezable = value as Freezable; if (valueAsFreezable != null) { if (!valueAsFreezable.Freeze(isChecking)) { if (TraceFreezable.IsEnabled) { TraceFreezable.Trace( TraceEventType.Warning, TraceFreezable.UnableToFreezeFreezableSubProperty, d, dp, dp.OwnerType); } return false; } } else // not a Freezable { DispatcherObject valueAsDispatcherObject = value as DispatcherObject; if (valueAsDispatcherObject != null) { if (valueAsDispatcherObject.Dispatcher == null) { // The property is a free-threaded DispatcherObject; since it's // already free-threaded it doesn't prevent this Freezable from // becoming free-threaded too. // It is up to the creator of this type to ensure that the // DispatcherObject is actually immutable } else { // The value of this property derives from DispatcherObject and // has thread affinity; return false. if (TraceFreezable.IsEnabled) { TraceFreezable.Trace( TraceEventType.Warning, TraceFreezable.UnableToFreezeDispatcherObjectWithThreadAffinity, d, dp, dp.OwnerType, valueAsDispatcherObject ); } return false; } } // The property isn't a DispatcherObject. It may be immutable (such as a string) // or the user may have made it thread-safe. It's up to the creator of the type to // do the right thing; we return true as an extensibility point. } } } return true; }
// // This method // 1. Is called from AncestorChange InvalidateTree. // 2. It is used to create the InheritableProperties on the given node. // 3. It also accumulates oldValues for the inheritable properties that are about to be invalidated // internal FrugalObjectList <DependencyProperty> CreateParentInheritableProperties( DependencyObject d, DependencyObject parent, bool isAddOperation) { Debug.Assert(d != null, "Must have non-null current node"); if (parent == null) { return(new FrugalObjectList <DependencyProperty>(0)); } DependencyObjectType treeObjDOT = d.DependencyObjectType; // See if we have a cached value. EffectiveValueEntry[] parentEffectiveValues = null; uint parentEffectiveValuesCount = 0; uint inheritablePropertiesCount = 0; // If inheritable properties aren't cached on you then use the effective // values cache on the parent to discover those inherited properties that // may need to be invalidated on the children nodes. if (!parent.IsSelfInheritanceParent) { DependencyObject inheritanceParent = parent.InheritanceParent; if (inheritanceParent != null) { parentEffectiveValues = inheritanceParent.EffectiveValues; parentEffectiveValuesCount = inheritanceParent.EffectiveValuesCount; inheritablePropertiesCount = inheritanceParent.InheritableEffectiveValuesCount; } } else { parentEffectiveValues = parent.EffectiveValues; parentEffectiveValuesCount = parent.EffectiveValuesCount; inheritablePropertiesCount = parent.InheritableEffectiveValuesCount; } FrugalObjectList <DependencyProperty> inheritableProperties = new FrugalObjectList <DependencyProperty>((int)inheritablePropertiesCount); if (inheritablePropertiesCount == 0) { return(inheritableProperties); } _rootInheritableValues = new InheritablePropertyChangeInfo[(int)inheritablePropertiesCount]; int inheritableIndex = 0; FrameworkObject foParent = new FrameworkObject(parent); for (uint i = 0; i < parentEffectiveValuesCount; i++) { // Add all the inheritable properties from the effectiveValues // cache to the TreeStateCache on the parent EffectiveValueEntry entry = parentEffectiveValues[i]; DependencyProperty dp = DependencyProperty.RegisteredPropertyList.List[entry.PropertyIndex]; // There are UncommonFields also stored in the EffectiveValues cache. We need to exclude those. if ((dp != null) && dp.IsPotentiallyInherited) { PropertyMetadata metadata = dp.GetMetadata(parent.DependencyObjectType); if (metadata != null && metadata.IsInherited) { Debug.Assert(!inheritableProperties.Contains(dp), "EffectiveValues cache must not contains duplicate entries for the same DP"); FrameworkPropertyMetadata fMetadata = (FrameworkPropertyMetadata)metadata; // Children do not need to inherit properties across a tree boundary // unless the property is set to override this behavior. if (!TreeWalkHelper.SkipNow(foParent.InheritanceBehavior) || fMetadata.OverridesInheritanceBehavior) { inheritableProperties.Add(dp); EffectiveValueEntry oldEntry; EffectiveValueEntry newEntry; oldEntry = d.GetValueEntry( d.LookupEntry(dp.GlobalIndex), dp, dp.GetMetadata(treeObjDOT), RequestFlags.DeferredReferences); if (isAddOperation) { // set up the new value newEntry = entry; if ((newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Default) || newEntry.HasModifiers) { newEntry = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved); newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } else { newEntry = new EffectiveValueEntry(); } _rootInheritableValues[inheritableIndex++] = new InheritablePropertyChangeInfo(d, dp, oldEntry, newEntry); if (inheritablePropertiesCount == inheritableIndex) { // no more inheritable properties, bail early break; } } } } } return(inheritableProperties); }
// Token: 0x06000C59 RID: 3161 RVA: 0x0002DFDC File Offset: 0x0002C1DC internal FrugalObjectList <DependencyProperty> CreateParentInheritableProperties(DependencyObject d, DependencyObject parent, bool isAddOperation) { if (parent == null) { return(new FrugalObjectList <DependencyProperty>(0)); } DependencyObjectType dependencyObjectType = d.DependencyObjectType; EffectiveValueEntry[] array = null; uint num = 0U; uint num2 = 0U; if (!parent.IsSelfInheritanceParent) { DependencyObject inheritanceParent = parent.InheritanceParent; if (inheritanceParent != null) { array = inheritanceParent.EffectiveValues; num = inheritanceParent.EffectiveValuesCount; num2 = inheritanceParent.InheritableEffectiveValuesCount; } } else { array = parent.EffectiveValues; num = parent.EffectiveValuesCount; num2 = parent.InheritableEffectiveValuesCount; } FrugalObjectList <DependencyProperty> frugalObjectList = new FrugalObjectList <DependencyProperty>((int)num2); if (num2 == 0U) { return(frugalObjectList); } this._rootInheritableValues = new InheritablePropertyChangeInfo[num2]; int num3 = 0; FrameworkObject frameworkObject = new FrameworkObject(parent); for (uint num4 = 0U; num4 < num; num4 += 1U) { EffectiveValueEntry effectiveValueEntry = array[(int)num4]; DependencyProperty dependencyProperty = DependencyProperty.RegisteredPropertyList.List[effectiveValueEntry.PropertyIndex]; if (dependencyProperty != null && dependencyProperty.IsPotentiallyInherited) { PropertyMetadata metadata = dependencyProperty.GetMetadata(parent.DependencyObjectType); if (metadata != null && metadata.IsInherited) { FrameworkPropertyMetadata frameworkPropertyMetadata = (FrameworkPropertyMetadata)metadata; if (!TreeWalkHelper.SkipNow(frameworkObject.InheritanceBehavior) || frameworkPropertyMetadata.OverridesInheritanceBehavior) { frugalObjectList.Add(dependencyProperty); EffectiveValueEntry valueEntry = d.GetValueEntry(d.LookupEntry(dependencyProperty.GlobalIndex), dependencyProperty, dependencyProperty.GetMetadata(dependencyObjectType), RequestFlags.DeferredReferences); EffectiveValueEntry newEntry; if (isAddOperation) { newEntry = effectiveValueEntry; if (newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Default || newEntry.HasModifiers) { newEntry = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved); newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } else { newEntry = default(EffectiveValueEntry); } this._rootInheritableValues[num3++] = new InheritablePropertyChangeInfo(d, dependencyProperty, valueEntry, newEntry); if ((ulong)num2 == (ulong)((long)num3)) { break; } } } } } return(frugalObjectList); }
// Consider the markup <Element A="x" B="{Binding...}"/>, and suppose // that setting A (to x) causes the element to assign a new value y for B. // (Lots of examples of this: e.g. setting Selector.SelectedIndex causes // Selector to assign a new value to Selector.SelectedItem.) The end // result depends on what order the assignments are done. If A=x happens // first, it assigns y to B but that is later overwritten by the // data-bound value z; if B happens first, the binding is installed and // produces the value z, then the assignment A=x sends the value y through // the binding (if it's two-way) to the data source. In other words, you // end up with z in the first case, but y in the second, and only the // second case changes the data source. // // The order of assignment (during initialization) is out of the user's // control, especially when the element is part of a template instance. // It can depend on the order in which static constructors are called, // which can vary depending on which elements appear first in the markup. // To mitigate this mysterious behavior, the following code attempts to // detect the situation and make it appear as if the binding always // happened first. internal bool ShouldUpdateWithCurrentValue(DependencyObject target, out object currentValue) { if (IsReflective) { // the bad situation only arises during initialization. After that, // the order of property assignments is determined by the app's // normal control flow. Unfortunately, we can only detect // initialization for framework elements; fortunately, this covers // all the known cases of the bad situation FrameworkObject fo = new FrameworkObject(target); if (!fo.IsInitialized) { // if the target property (B) already has a changed value (y), // we're in the bad situation and should propagate y back to // the data source DependencyProperty dp = TargetProperty; EntryIndex entryIndex = target.LookupEntry(dp.GlobalIndex); if (entryIndex.Found) { EffectiveValueEntry entry = target.GetValueEntry(entryIndex, dp, null, RequestFlags.RawEntry); if (entry.IsCoercedWithCurrentValue) { currentValue = entry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; if (entry.IsDeferredReference) { DeferredReference deferredReference = (DeferredReference)currentValue; currentValue = deferredReference.GetValue(entry.BaseValueSourceInternal); } return true; } } } } currentValue = null; return false; }
/// <summary> /// Callback on visiting each node in the descendency /// during an inheritable property change /// </summary> private static bool OnInheritablePropertyChanged( DependencyObject d, InheritablePropertyChangeInfo info, bool visitedViaVisualTree) { Debug.Assert(d != null, "Must have non-null current node"); DependencyProperty dp = info.Property; EffectiveValueEntry oldEntry = info.OldEntry; EffectiveValueEntry newEntry = info.NewEntry; InheritanceBehavior inheritanceBehavior; bool inheritanceNode = IsInheritanceNode(d, dp, out inheritanceBehavior); bool isForceInheritedProperty = IsForceInheritedProperty(dp); // Note that if a node is marked SkipNext means it hasn't acquired any values from its parent and // hence we do not need to invalidate this node or any of its descendents. However if a node is // marked SkipNow then this node might have acquired values from its parent but none of its // descendents would. Hence in this case we process the current node but omit all of its descendents. if (inheritanceNode && (!SkipNext(inheritanceBehavior) || isForceInheritedProperty)) { PropertyMetadata metadata = dp.GetMetadata(d); EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex); // Found an inheritance node if (!d.IsSelfInheritanceParent) { DependencyObject parent = FrameworkElement.GetFrameworkParent(d); InheritanceBehavior parentInheritanceBehavior = InheritanceBehavior.Default; if (parent != null) { FrameworkObject parentFO = new FrameworkObject(parent, true); parentInheritanceBehavior = parentFO.InheritanceBehavior; } if (!SkipNext(inheritanceBehavior) && !SkipNow(parentInheritanceBehavior)) { // Synchronize InheritanceParent d.SynchronizeInheritanceParent(parent); } // What should the oldValueSource on the child be? // When the oldValue on the parent was default it // means that the child also used its own default // and did not inherit from the parent. However // when the value on the parent was non-default // it means that the child inherited it. // Note that the oldValueSource on inheritablePropertyChangedData // is actually the parent's oldValueSource if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) { // we use an empty EffectiveValueEntry as a signal that the old entry was the default value oldEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(d, dp)); } } else { oldEntry = d.GetValueEntry( entryIndex, dp, metadata, RequestFlags.RawEntry); } // If the oldValueSource is of lower precedence than Inheritance // only then do we need to Invalidate the property if (BaseValueSourceInternal.Inherited >= oldEntry.BaseValueSourceInternal) { if (visitedViaVisualTree && FrameworkElement.DType.IsInstanceOfType(d)) { DependencyObject logicalParent = LogicalTreeHelper.GetParent(d); if (logicalParent != null) { DependencyObject visualParent = VisualTreeHelper.GetParent(d); if (visualParent != null && visualParent != logicalParent) { // Consider the following logical tree configuration. In this case we want // to RibbonToggleButton to pick up the new DataContext flowing in from // the Window. // // Window (info.RootElement) // ... // RibbonGroup (IsCollapsed) // RibbonControl (only in visual tree) // RibbonToggleButton // // Consider the following logical tree configuration. In this case we do not // want to RibbonToggleButton to change its DataContext because the changes // are only within the visual tree. // // Window // ... // RibbonGroup (IsCollapsed) // RibbonControl (only in visual tree) (info.RootElement) // RibbonToggleButton // // Saying it another way, the RibbonToggleButton in the above case belongs in a // different logical tree than the one that the current invalidation storm begun. // // Any change in an inheritable property begins an invalidation storm using the // DescendentsWalker and configures it to first traverse the logical children // and then visual children. Also nodes that have previously been visited via the // logical tree do not get visited again through the visual tree. I use this very // behavior as the basis for detecting nodes such as RibbonToggleButton. If the // RibbonToggleButton is being visisted for the first time via the visual tree then // the invalidation storm did not include its logical parent. And therefore the // RibbonToggleButton can early out of this storm. return false; } } } // Since we do not hold a cache of the oldValue we need to supply one // in order to correctly fire the change notification return (d.UpdateEffectiveValue( entryIndex, dp, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Inherit) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } else if (isForceInheritedProperty) { // IsCoerced == true && value == UnsetValue indicates that we need to re-coerce this value newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); // Re-coerce a force inherited property because it's coersion depends on treeness return (d.UpdateEffectiveValue( d.LookupEntry(dp.GlobalIndex), dp, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Inherit) & (UpdateResult.ValueChanged | UpdateResult.InheritedValueOverridden)) == UpdateResult.ValueChanged; // return false if either the value didn't change or // it changed because the inherited value was overridden by coercion or animation. } else { return false; } } // Do not continue walk down subtree if the walk was forced to stop // (due to separated trees) return (inheritanceBehavior == InheritanceBehavior.Default || isForceInheritedProperty); }
private static bool DefaultFreezeValueCallback( DependencyObject d, DependencyProperty dp, EntryIndex entryIndex, PropertyMetadata metadata, bool isChecking) { // The expression check only needs to be done when isChecking is true // because if we return false here the Freeze() call will fail. if (isChecking) { if (d.HasExpression(entryIndex, dp)) { if (TraceFreezable.IsEnabled) { TraceFreezable.Trace( TraceEventType.Warning, TraceFreezable.UnableToFreezeExpression, d, dp, dp.OwnerType); } return(false); } } if (!dp.IsValueType) { object value = d.GetValueEntry( entryIndex, dp, metadata, RequestFlags.FullyResolved).Value; if (value != null) { Freezable valueAsFreezable = value as Freezable; if (valueAsFreezable != null) { if (!valueAsFreezable.Freeze(isChecking)) { if (TraceFreezable.IsEnabled) { TraceFreezable.Trace( TraceEventType.Warning, TraceFreezable.UnableToFreezeFreezableSubProperty, d, dp, dp.OwnerType); } return(false); } } else // not a Freezable { DispatcherObject valueAsDispatcherObject = value as DispatcherObject; if (valueAsDispatcherObject != null) { if (valueAsDispatcherObject.Dispatcher == null) { // The property is a free-threaded DispatcherObject; since it's // already free-threaded it doesn't prevent this Freezable from // becoming free-threaded too. // It is up to the creator of this type to ensure that the // DispatcherObject is actually immutable } else { // The value of this property derives from DispatcherObject and // has thread affinity; return false. if (TraceFreezable.IsEnabled) { TraceFreezable.Trace( TraceEventType.Warning, TraceFreezable.UnableToFreezeDispatcherObjectWithThreadAffinity, d, dp, dp.OwnerType, valueAsDispatcherObject); } return(false); } } // The property isn't a DispatcherObject. It may be immutable (such as a string) // or the user may have made it thread-safe. It's up to the creator of the type to // do the right thing; we return true as an extensibility point. } } } return(true); }