internal static EffectiveValueEntry CreateDefaultValueEntry(DependencyProperty dp, object value) { EffectiveValueEntry entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default); entry.Value = value; return(entry); }
internal static EffectiveValueEntry CreateDefaultValueEntry(DependencyProperty dp, object value) { EffectiveValueEntry entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default); entry.Value = value; return entry; }
internal DependencyPropertyChangedEventArgs( DependencyProperty property, PropertyMetadata metadata, bool isAValueChange, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, OperationType operationType) { _property = property; _metadata = metadata; _oldEntry = oldEntry; _newEntry = newEntry; _flags = 0; _operationType = operationType; IsAValueChange = isAValueChange; // This is when a mutable default is promoted to a local value. On this operation mutable default // value acquires a freezable context. However this value promotion operation is triggered // whenever there has been a sub property change to the mutable default. Eg. Adding a TextEffect // to a TextEffectCollection instance which is the mutable default. Since we missed the sub property // change due to this add, we flip the IsASubPropertyChange bit on the following change caused by // the value promotion to coalesce these operations. IsASubPropertyChange = (operationType == OperationType.ChangeMutableDefaultValue); }
internal InheritablePropertyChangeInfo( DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry) { _property = property; _oldEntry = oldEntry; _newEntry = newEntry; }
internal InheritablePropertyChangeInfo( DependencyObject rootElement, DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry) { _rootElement = rootElement; _property = property; _oldEntry = oldEntry; _newEntry = newEntry; }
// 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); }
internal DependencyPropertyChangedEventArgs(DependencyProperty property, PropertyMetadata metadata, object value) { _property = property; _metadata = metadata; _oldEntry = new EffectiveValueEntry(property); _oldEntry.Value = value; _newEntry = _oldEntry; _flags = 0; _operationType = OperationType.Unknown; IsASubPropertyChange = true; }
/// <summary> /// Initializes a new instance of the DependencyPropertyChangedEventArgs class. /// </summary> /// <param name="property"> /// The property whose value changed. /// </param> /// <param name="oldValue"> /// The value of the property before the change. /// </param> /// <param name="newValue"> /// The value of the property after the change. /// </param> public DependencyPropertyChangedEventArgs(DependencyProperty property, object oldValue, object newValue) { _property = property; _metadata = null; _oldEntry = new EffectiveValueEntry(property); _newEntry = _oldEntry; _oldEntry.Value = oldValue; _newEntry.Value = newValue; _flags = 0; _operationType = OperationType.Unknown; IsAValueChange = true; }
[FriendAccessAllowed] // Declared in Base also used in Framework internal UpdateResult UpdateEffectiveValue( EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, ref EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, OperationType operationType) { if (dp == null) { throw new ArgumentNullException("dp"); } #region EventTracing #if VERBOSE_PROPERTY_EVENT bool isDynamicTracing = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); // This was under "normal" if (isDynamicTracing) { ++InvalidationCount; if( InvalidationCount % 100 == 0 ) { EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, MS.Utility.EventType.Info, InvalidationCount ); } string TypeAndName = String.Format(CultureInfo.InvariantCulture, "[{0}]{1}({2})",GetType().Name,dp.Name,base.GetHashCode()); // FxCop wanted the CultureInfo.InvariantCulture EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, MS.Utility.EventType.StartEvent, base.GetHashCode(), TypeAndName); // base.GetHashCode() to avoid calling a virtual, which FxCop doesn't like. } #endif #endregion EventTracing #if NESTED_OPERATIONS_CHECK // Are we invalidating out of control? if( NestedOperations > NestedOperationMaximum ) { // We're invalidating out of control, time to abort. throw new InvalidOperationException("Too many levels of nested DependencyProperty invalidations. This usually indicates a circular reference in the application and the cycle needs to be broken."); } NestedOperations++; // Decrement in the finally block #endif int targetIndex = dp.GlobalIndex; if (oldEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) { // Do a full get value of the old entry if it isn't supplied. // It isn't supplied in cases where we are *unsetting* a value // (e.g. ClearValue, style unapply, trigger unapply) oldEntry = GetValueEntry( entryIndex, dp, metadata, RequestFlags.RawEntry); } object oldValue = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; /* if( TraceDependencyProperty.IsEnabled ) { TraceDependencyProperty.Trace( TraceEventType.Verbose, TraceDependencyProperty.UpdateEffectiveValueStart, this, dp, dp.OwnerType, oldValue, oldEntry.BaseValueSourceInternal ); } */ // for control-value coercion, extract the desired control value, then // reset the new entry to ask for a re-evaluation with coercion object controlValue = null; if (coerceWithCurrentValue) { controlValue = newEntry.Value; newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); } // check for early-out opportunities: // 1) the new entry is of lower priority than the current entry if ((newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Unknown) && (newEntry.BaseValueSourceInternal < oldEntry.BaseValueSourceInternal)) { return 0; } bool isReEvaluate = false; bool isCoerceValue = false; bool isClearValue = false; if (newEntry.Value == DependencyProperty.UnsetValue) { FullValueSource fullValueSource = newEntry.FullValueSource; isCoerceValue = (fullValueSource == FullValueSource.IsCoerced); isReEvaluate = true; if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Local) { isClearValue = true; } } // if we're not in an animation update (caused by AnimationStorage.OnCurrentTimeInvalidated) // then always force a re-evaluation if (a) there was an animation in play or (b) there's // an expression evaluation to be made if (isReEvaluate || (!newEntry.IsAnimated && (oldEntry.IsAnimated || (oldEntry.IsExpression && newEntry.IsExpression && (newEntry.ModifiedValue.BaseValue == oldEntry.ModifiedValue.BaseValue))))) { // we have to compute the new value if (!isCoerceValue) { newEntry = EvaluateEffectiveValue(entryIndex, dp, metadata, oldEntry, newEntry, operationType); // Make sure that the call out did not cause a change to entryIndex entryIndex = CheckEntryIndex(entryIndex, targetIndex); bool found = (newEntry.Value != DependencyProperty.UnsetValue); if (!found && metadata.IsInherited) { DependencyObject inheritanceParent = InheritanceParent; if (inheritanceParent != null) { // Fetch the IsDeferredValue flag from the InheritanceParent EntryIndex parentEntryIndex = inheritanceParent.LookupEntry(dp.GlobalIndex); if (parentEntryIndex.Found) { found = true; newEntry = inheritanceParent._effectiveValues[parentEntryIndex.Index].GetFlattenedEntry(RequestFlags.FullyResolved); newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } } // interesting that I just had to add this ... suggests that we are now overinvalidating if (!found) { newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); } } else { if (!oldEntry.HasModifiers) { newEntry = oldEntry; } else { newEntry = new EffectiveValueEntry(dp, oldEntry.BaseValueSourceInternal); ModifiedValue modifiedValue = oldEntry.ModifiedValue; object baseValue = modifiedValue.BaseValue; newEntry.Value = baseValue; newEntry.HasExpressionMarker = oldEntry.HasExpressionMarker; if (oldEntry.IsExpression) { newEntry.SetExpressionValue(modifiedValue.ExpressionValue, baseValue); } if (oldEntry.IsAnimated) { newEntry.SetAnimatedValue(modifiedValue.AnimatedValue, baseValue); } } } } // Coerce to current value if (coerceWithCurrentValue) { object baseValue = newEntry.GetFlattenedEntry(RequestFlags.CoercionBaseValue).Value; ProcessCoerceValue( dp, metadata, ref entryIndex, ref targetIndex, ref newEntry, ref oldEntry, ref oldValue, baseValue, controlValue, null /*coerceValueCallback */, coerceWithDeferredReference, coerceWithCurrentValue, false /*skipBaseValueChecks*/); // Make sure that the call out did not cause a change to entryIndex entryIndex = CheckEntryIndex(entryIndex, targetIndex); } // Coerce Value if (metadata.CoerceValueCallback != null && !(isClearValue && newEntry.FullValueSource == (FullValueSource)BaseValueSourceInternal.Default)) { // CALLBACK object baseValue = newEntry.GetFlattenedEntry(RequestFlags.CoercionBaseValue).Value; ProcessCoerceValue( dp, metadata, ref entryIndex, ref targetIndex, ref newEntry, ref oldEntry, ref oldValue, baseValue, null /* controlValue */, metadata.CoerceValueCallback, coerceWithDeferredReference, false /* coerceWithCurrentValue */, false /*skipBaseValueChecks*/); // Make sure that the call out did not cause a change to entryIndex entryIndex = CheckEntryIndex(entryIndex, targetIndex); } // The main difference between this callback and the metadata.CoerceValueCallback is that // designers want to be able to coerce during all value changes including a change to the // default value. Whereas metadata.CoerceValueCallback coerces all property values but the // default, because default values are meant to fit automatically fit into the coersion constraint. if (dp.DesignerCoerceValueCallback != null) { // During a DesignerCoerceValueCallback the value obtained is stored in the same // member as the metadata.CoerceValueCallback. In this case we do not store the // baseValue in the entry. Thus the baseValue checks will the violated. That is the // reason for skipping these checks in this one case. // Also before invoking the DesignerCoerceValueCallback the baseValue must // always be expanded if it is a DeferredReference ProcessCoerceValue( dp, metadata, ref entryIndex, ref targetIndex, ref newEntry, ref oldEntry, ref oldValue, newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value, null /*controlValue*/, dp.DesignerCoerceValueCallback, false /*coerceWithDeferredReference*/, false /*coerceWithCurrentValue*/, true /*skipBaseValueChecks*/); // Make sure that the call out did not cause a change to entryIndex entryIndex = CheckEntryIndex(entryIndex, targetIndex); } UpdateResult result = 0; if (newEntry.FullValueSource != (FullValueSource) BaseValueSourceInternal.Default) { Debug.Assert(newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Unknown, "Value source should be known at this point"); bool unsetValue = false; if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Inherited) { if (DependencyObject.IsTreeWalkOperation(operationType) && (newEntry.IsCoerced || newEntry.IsAnimated)) { // an inherited value has been coerced or animated. This // should be treated as a new "set" of the property. // The current tree walk should not continue into the subtree, // but rather a new tree walk should start. // this signals OnPropertyChanged to start a new tree walk // and mark the current node as SelfInheritanceParent operationType = OperationType.Unknown; // this signals the caller not to continue the current // tree walk into the subtree result |= UpdateResult.InheritedValueOverridden; } else if (!IsSelfInheritanceParent) { // otherwise, just inherit the value from the InheritanceParent unsetValue = true; } } if (unsetValue) { UnsetEffectiveValue(entryIndex, dp, metadata); } else { SetEffectiveValue(entryIndex, dp, metadata, newEntry, oldEntry); } } else { UnsetEffectiveValue(entryIndex, dp, metadata); } // Change notifications are fired when the value actually changed or in // the case of the Freezable mutable factories when the value source changes. // Try AvaCop without the second condition to repro this problem. bool isAValueChange = !Equals(dp, oldValue, newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value); if (isAValueChange) { result |= UpdateResult.ValueChanged; } if (isAValueChange || (operationType == OperationType.ChangeMutableDefaultValue && oldEntry.BaseValueSourceInternal != newEntry.BaseValueSourceInternal) || (metadata.IsInherited && oldEntry.BaseValueSourceInternal != newEntry.BaseValueSourceInternal && operationType != OperationType.AddChild && operationType != OperationType.RemoveChild && operationType != OperationType.Inherit)) { result |= UpdateResult.NotificationSent; try { // fire change notification NotifyPropertyChange( new DependencyPropertyChangedEventArgs( dp, metadata, isAValueChange, oldEntry, newEntry, operationType)); } finally { #if NESTED_OPERATIONS_CHECK NestedOperations--; #endif } } #region EventTracing #if VERBOSE_PROPERTY_EVENT if (isDynamicTracing) { if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) { EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYINVALIDATIONGUID, MS.Utility.EventType.EndEvent); } } #endif #endregion EventTracing /* if( TraceDependencyProperty.IsEnabled ) { TraceDependencyProperty.Trace( TraceEventType.Verbose, TraceDependencyProperty.UpdateEffectiveValueStop, this, dp, dp.OwnerType, newEntry.Value, newEntry.BaseValueSourceInternal ); } */ // There are two cases in which we need to adjust inheritance contexts: // // 1. The value pointed to this DP has changed, in which case // we need to move the context from the old value to the // new value. // // 2. The value has not changed, but the ValueSource for the // property has. (For example, we've gone from being a local // value to the result of a binding expression that just // happens to return the same DO instance.) In which case // we may need to add or remove contexts even though we // did not raise change notifications. // // We don't want to provide an inheritance context if the entry is // animated, coerced, is an expression, is coming from a style or // template, etc. To avoid this, we explicitly check that the // FullValueSource is Local. By checking FullValueSource rather than // BaseValueSource we are implicitly filtering out any sources which // have modifiers. (e.g., IsExpression, IsAnimated, etc.) bool oldEntryHadContext = oldEntry.FullValueSource == (FullValueSource) BaseValueSourceInternal.Local; bool newEntryNeedsContext = newEntry.FullValueSource == (FullValueSource) BaseValueSourceInternal.Local; // NOTE: We use result rather than isAValueChange below so that we // pick up mutable default promotion, etc. if (result != 0 || (oldEntryHadContext != newEntryNeedsContext)) { if (oldEntryHadContext) { // RemoveSelfAsInheritanceContext no-ops null, non-DO values, etc. RemoveSelfAsInheritanceContext(oldEntry.LocalValue, dp); } // Become the context for the new value. This is happens after // invalidation so that FE has a chance to hookup the logical // tree first. This is done only if the current DependencyObject // wants to be in the InheritanceContext tree. if (newEntryNeedsContext) { // ProvideSelfAsInheritanceContext no-ops null, non-DO values, etc. ProvideSelfAsInheritanceContext(newEntry.LocalValue, dp); } // DANGER: Callout might add/remove entries in the effective value table. // Uncomment the following if you need to use entryIndex post // context hookup. // // entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } return result; }
/// <summary> /// Invalidates a property /// </summary> /// <param name="dp">Dependency property</param> //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 public void InvalidateProperty(DependencyProperty dp) { // Do not allow foreign threads access. // (This is a noop if this object is not assigned to a Dispatcher.) // this.VerifyAccess(); if (dp == null) { throw new ArgumentNullException("dp"); } EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Unknown); UpdateEffectiveValue( LookupEntry(dp.GlobalIndex), dp, dp.GetMetadata(DependencyObjectType), new EffectiveValueEntry() /* oldEntry */, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithControlReference */, OperationType.Unknown); }
/// <summary> /// Coerce a property value /// </summary> /// <param name="dp">Dependency property</param> public void CoerceValue(DependencyProperty dp) { // Do not allow foreign threads access. // (This is a noop if this object is not assigned to a Dispatcher.) // this.VerifyAccess(); EntryIndex entryIndex = LookupEntry(dp.GlobalIndex); PropertyMetadata metadata = dp.GetMetadata(DependencyObjectType); // if the property has a coerced-with-control value, apply the coercion // to that value. This is done by simply calling SetCurrentValue. if (entryIndex.Found) { EffectiveValueEntry entry = GetValueEntry(entryIndex, dp, metadata, RequestFlags.RawEntry); if (entry.IsCoercedWithCurrentValue) { SetCurrentValue(dp, entry.ModifiedValue.CoercedValue); return; } } // IsCoerced == true && value == UnsetValue indicates that we need to re-coerce this value EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, FullValueSource.IsCoerced); UpdateEffectiveValue( entryIndex, dp, metadata, new EffectiveValueEntry() /* oldEntry */, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown); }
private bool ReceivePropertySet(object targetObject, XamlMember member, object value, DependencyObject templatedParent) { DependencyObject dependencyObject = targetObject as DependencyObject; DependencyProperty dependencyProperty; System.Windows.Baml2006.WpfXamlMember wpfMember = member as System.Windows.Baml2006.WpfXamlMember; if (wpfMember != null) { dependencyProperty = wpfMember.DependencyProperty; } else { // All DP backed XamlMembers must be wrapped by the WpfXamlMember. If it isn't wrapped, then it's not a DP return false; } //If we're not dealing with a DO or a DP, we cannot set an EffectiveValueEntry if (dependencyProperty == null || dependencyObject == null) { return false; } FrameworkObject fo = new FrameworkObject(dependencyObject); // If this isn't an FE that we're optimizing, defer to base. // // Similarly, if we don't have a templated parent, we're not optimizing, and defer to base // (This happens when FrameworkTemplate.LoadContent() is called.) if ((fo.TemplatedParent == null) || (templatedParent == null)) { return false; } // For template content, we skip the automatic BaseUriProperty and the UidProperty // (Implementation note: Doing this here because this is what we did with FEFs, // and because automation gets confused if the Uid isn't unique in the whole tree). if (dependencyProperty == System.Windows.Navigation.BaseUriHelper.BaseUriProperty) { // We only skip the automatic BaseUri property. If it's set explicitely, // that's passed through. if (!fo.IsInitialized) { return true; } } else if (dependencyProperty == UIElement.UidProperty) { return true; } Debug.Assert(fo.TemplatedParent == templatedParent); // Set the value onto the FE/FCE. HybridDictionary parentTemplateValues; if (!fo.StoresParentTemplateValues) { parentTemplateValues = new HybridDictionary(); StyleHelper.ParentTemplateValuesField.SetValue(dependencyObject, parentTemplateValues); fo.StoresParentTemplateValues = true; } else { parentTemplateValues = StyleHelper.ParentTemplateValuesField.GetValue(dependencyObject); } // Check if it is an expression Expression expr; int childIndex = fo.TemplateChildIndex; if ((expr = value as Expression) != null) { BindingExpressionBase bindingExpr; TemplateBindingExpression templateBindingExpr; if ((bindingExpr = expr as BindingExpressionBase) != null) { // If this is a BindingExpression then we need to store the corresponding // MarkupExtension into the per instance store for the unshared DP value. // Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, templatedParent, InstanceStyleData.InstanceValues); StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dependencyProperty, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/); value = bindingExpr.ParentBindingBase; } else if ((templateBindingExpr = expr as TemplateBindingExpression) != null) { // If this is a TemplateBindingExpression then we create an equivalent Binding // MarkupExtension and store that in the per instance store for the unshared DP // value. We use Binding here because it has all the wiring in place to handle // change notifications through DependencySource and such. TemplateBindingExtension templateBindingExtension = templateBindingExpr.TemplateBindingExtension; // Allocate a slot for this unshared DP value in the per-instance store for MarkupExtensions HybridDictionary instanceValues = StyleHelper.EnsureInstanceData(StyleHelper.TemplateDataField, templatedParent, InstanceStyleData.InstanceValues); StyleHelper.ProcessInstanceValue(dependencyObject, childIndex, instanceValues, dependencyProperty, StyleHelper.UnsharedTemplateContentPropertyIndex, true /*apply*/); // Create a Binding equivalent to the TemplateBindingExtension Binding binding = new Binding(); binding.Mode = BindingMode.OneWay; binding.RelativeSource = RelativeSource.TemplatedParent; binding.Path = new PropertyPath(templateBindingExtension.Property); binding.Converter = templateBindingExtension.Converter; binding.ConverterParameter = templateBindingExtension.ConverterParameter; value = binding; } else { Debug.Assert(false, "We do not have support for DynamicResource within unshared template content"); } } bool isMarkupExtension = value is MarkupExtension; // Value needs to be valid for the DP, or Binding/MultiBinding/PriorityBinding/TemplateBinding. if (!dependencyProperty.IsValidValue(value)) { if (!isMarkupExtension && !(value is DeferredReference)) { throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dependencyProperty.Name)); } } parentTemplateValues[dependencyProperty] = value; dependencyObject.ProvideSelfAsInheritanceContext(value, dependencyProperty); EffectiveValueEntry entry = new EffectiveValueEntry(dependencyProperty); entry.BaseValueSourceInternal = BaseValueSourceInternal.ParentTemplate; entry.Value = value; if (isMarkupExtension) { // entry will be updated to hold the value StyleHelper.GetInstanceValue( StyleHelper.TemplateDataField, templatedParent, fo.FE, fo.FCE, childIndex, dependencyProperty, StyleHelper.UnsharedTemplateContentPropertyIndex, ref entry); } dependencyObject.UpdateEffectiveValue( dependencyObject.LookupEntry(dependencyProperty.GlobalIndex), dependencyProperty, dependencyProperty.GetMetadata(dependencyObject.DependencyObjectType), new EffectiveValueEntry() /* oldEntry */, ref entry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown); return true; }
internal sealed override void EvaluateAnimatedValueCore( DependencyProperty dp, PropertyMetadata metadata, ref EffectiveValueEntry entry) { if (IAnimatable_HasAnimatedProperties) { AnimationStorage storage = AnimationStorage.GetStorage(this, dp); if (storage != null) { storage.EvaluateAnimatedValue(metadata, ref entry); } } }
// 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); }
//[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 private EffectiveValueEntry EvaluateEffectiveValue( EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, // this is only used to recognize if this is a clear local value OperationType operationType) { #region EventTracing #if VERBOSE_PROPERTY_EVENT bool isDynamicTracing = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); // This was under "normal" if (isDynamicTracing) { ++ValidationCount; if( ValidationCount % 100 == 0 ) { EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID, MS.Utility.EventType.Info, ValidationCount ); } string TypeAndName = String.Format(CultureInfo.InvariantCulture, "[{0}]{1}({2})",GetType().Name,dp.Name,base.GetHashCode()); // FxCop wanted the CultureInfo.InvariantCulture EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID, MS.Utility.EventType.StartEvent, base.GetHashCode(), TypeAndName ); // base.GetHashCode() to avoid calling a virtual, which FxCop doesn't like. } #endif #endregion EventTracing #if NESTED_OPERATIONS_CHECK // Are we validating out of control? if( NestedOperations > NestedOperationMaximum ) { // We're validating out of control, time to abort. throw new InvalidOperationException("Too many levels of nested DependencyProperty GetValue calls. This usually indicates a circular reference in the application and the cycle needs to be broken."); } NestedOperations++; // Decrement in the finally block #endif object value = DependencyProperty.UnsetValue; try { // Read local storage bool isSetValue = (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Local); bool isClearLocalValue = isSetValue && (newEntry.Value == DependencyProperty.UnsetValue); bool oldLocalIsExpression = false; if (isClearLocalValue) { newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Unknown; } else { // if we reached this on a re-evaluate of a setvalue, we need to make sure // we don't lose track of the newly specified local value. // for all other cases, the oldEntry will have the local value we should // use. value = isSetValue ? newEntry.LocalValue : oldEntry.LocalValue; if (value == ExpressionInAlternativeStore) { value = DependencyProperty.UnsetValue; } else { oldLocalIsExpression = isSetValue ? newEntry.IsExpression : oldEntry.IsExpression; } } // (If local storage not Unset and not an Expression, return) if (value != DependencyProperty.UnsetValue) { newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local); newEntry.Value = value; // Check if an Expression is set if (oldLocalIsExpression) { // CALLBACK newEntry = EvaluateExpression( entryIndex, dp, (Expression) value, metadata, oldEntry, newEntry); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); value = newEntry.ModifiedValue.ExpressionValue; } } // Subclasses are not allowed to resolve/modify the value for read-only properties. if( !dp.ReadOnly ) { // Give subclasses a chance to resolve/modify the value EvaluateBaseValueCore(dp, metadata, ref newEntry); // we need to have the default value in the entry before we do the animation check if (newEntry.BaseValueSourceInternal == BaseValueSourceInternal.Unknown) { newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); } value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); if (oldEntry.IsAnimated) { newEntry.ResetCoercedValue(); EvaluateAnimatedValueCore(dp, metadata, ref newEntry); value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; } } } finally { #if NESTED_OPERATIONS_CHECK NestedOperations--; #endif } #region EventTracing #if VERBOSE_PROPERTY_EVENT if (isDynamicTracing) { if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) { int UsingDefault = 1; if (value != DependencyProperty.UnsetValue) UsingDefault = 0; EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYVALIDATIONGUID, MS.Utility.EventType.EndEvent, UsingDefault); } } #endif #endregion EventTracing if (value == DependencyProperty.UnsetValue) { newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); } return newEntry; }
/// <summary> /// The common code shared by all variants of ClearValue /// </summary> private void ClearValueCommon(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata) { if (IsSealed) { throw new InvalidOperationException(SR.Get(SRID.ClearOnReadOnlyObjectNotAllowed, this)); } // Get old value EffectiveValueEntry oldEntry = GetValueEntry( entryIndex, dp, metadata, RequestFlags.RawEntry); // Get current local value // (No need to go through read local callback, just checking // for presence of Expression) object current = oldEntry.LocalValue; // Get current expression Expression currentExpr = (oldEntry.IsExpression) ? (current as Expression) : null; // Inform value expression of detachment, if applicable if (currentExpr != null) { // CALLBACK DependencySource[] currentSources = currentExpr.GetSources(); UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false); // Remove // CALLBACK currentExpr.OnDetach(this, dp); currentExpr.MarkDetached(); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } // valuesource == Local && value == UnsetValue indicates that we are clearing the local value EffectiveValueEntry newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local); // Property is now invalid UpdateEffectiveValue( entryIndex, dp, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, false /* coerceWithCurrentValue */, OperationType.Unknown); }
[FriendAccessAllowed] // Built into Base, also used by Core and Framework. internal void SetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, int targetIndex, PropertyMetadata metadata, object value, BaseValueSourceInternal valueSource) { Debug.Assert(value != DependencyProperty.UnsetValue, "Value to be set cannot be UnsetValue"); Debug.Assert(valueSource != BaseValueSourceInternal.Unknown, "ValueSource cannot be Unknown"); // For thread-safety, sealed DOs can't modify _effectiveValues. Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified"); if (metadata != null && metadata.IsInherited && valueSource != BaseValueSourceInternal.Inherited && !IsSelfInheritanceParent) { SetIsSelfInheritanceParent(); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } EffectiveValueEntry entry; if (entryIndex.Found) { entry = _effectiveValues[entryIndex.Index]; } else { entry = new EffectiveValueEntry(); entry.PropertyIndex = targetIndex; InsertEntry(entry, entryIndex.Index); if (metadata != null && metadata.IsInherited) { InheritableEffectiveValuesCount++; } } bool hasExpressionMarker = (value == ExpressionInAlternativeStore); if (!hasExpressionMarker && entry.HasExpressionMarker && (valueSource == BaseValueSourceInternal.ThemeStyle || valueSource == BaseValueSourceInternal.ThemeStyleTrigger || valueSource == BaseValueSourceInternal.Style || valueSource == BaseValueSourceInternal.TemplateTrigger || valueSource == BaseValueSourceInternal.StyleTrigger || valueSource == BaseValueSourceInternal.ParentTemplate || valueSource == BaseValueSourceInternal.ParentTemplateTrigger)) { entry.BaseValueSourceInternal = valueSource; entry.SetExpressionValue(value, ExpressionInAlternativeStore); entry.ResetAnimatedValue(); entry.ResetCoercedValue(); } else if (entry.IsExpression && entry.ModifiedValue.ExpressionValue == Expression.NoValue) { // we now have a value for an expression that is "hiding" - save it // as the expression value entry.SetExpressionValue(value, entry.ModifiedValue.BaseValue); } else { Debug.Assert(entry.BaseValueSourceInternal != BaseValueSourceInternal.Local || valueSource == BaseValueSourceInternal.Local, "No one but another local value can stomp over an existing local value. The only way is to clear the entry"); entry.BaseValueSourceInternal = valueSource; entry.ResetValue(value, hasExpressionMarker); } Debug.Assert(dp == null || (dp.GlobalIndex == entry.PropertyIndex), "EffectiveValueEntry & DependencyProperty do not match"); _effectiveValues[entryIndex.Index] = entry; }
// insert the given entry at the given index // this function assumes that entryIndex is at the right // location such that the resulting list remains sorted by EffectiveValueEntry.PropertyIndex private void InsertEntry(EffectiveValueEntry entry, uint entryIndex) { // For thread-safety, sealed DOs can't modify _effectiveValues. Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified"); #if DEBUG EntryIndex debugIndex = LookupEntry(entry.PropertyIndex); Debug.Assert(!debugIndex.Found && debugIndex.Index == entryIndex, "Inserting duplicate"); #endif if (CanModifyEffectiveValues == false) { throw new InvalidOperationException(SR.Get(SRID.LocalValueEnumerationInvalidated)); } uint effectiveValuesCount = EffectiveValuesCount; if (effectiveValuesCount > 0) { if (_effectiveValues.Length == effectiveValuesCount) { int newSize = (int) (effectiveValuesCount * (IsInPropertyInitialization ? 2.0 : 1.2)); if (newSize == effectiveValuesCount) { newSize++; } EffectiveValueEntry[] destEntries = new EffectiveValueEntry[newSize]; Array.Copy(_effectiveValues, 0, destEntries, 0, entryIndex); destEntries[entryIndex] = entry; Array.Copy(_effectiveValues, entryIndex, destEntries, entryIndex + 1, effectiveValuesCount - entryIndex); _effectiveValues = destEntries; } else { Array.Copy(_effectiveValues, entryIndex, _effectiveValues, entryIndex + 1, effectiveValuesCount - entryIndex); _effectiveValues[entryIndex] = entry; } } else { if (_effectiveValues == null) { _effectiveValues = new EffectiveValueEntry[EffectiveValuesInitialSize]; } _effectiveValues[0] = entry; } EffectiveValuesCount = effectiveValuesCount + 1; }
/// <summary> /// Allows subclasses to participate in property animated value computation /// </summary> internal virtual void EvaluateAnimatedValueCore( DependencyProperty dp, PropertyMetadata metadata, ref EffectiveValueEntry newEntry) { }
internal EffectiveValueEntry GetFlattenedEntry(RequestFlags requests) { if ((_source & (FullValueSource.ModifiersMask | FullValueSource.HasExpressionMarker)) == 0) { // If the property does not have any modifiers // then just return the base value. return(this); } if (!HasModifiers) { Debug.Assert(HasExpressionMarker); // This is the case when some one stuck an expression into // an alternate store such as a style or a template but the // new value for the expression has not been evaluated yet. // In the intermediate we need to return the default value // for the property. This problem was manifested in DRTDocumentViewer. EffectiveValueEntry unsetEntry = new EffectiveValueEntry(); unsetEntry.BaseValueSourceInternal = BaseValueSourceInternal; unsetEntry.PropertyIndex = PropertyIndex; return(unsetEntry); } // else entry has modifiers EffectiveValueEntry entry = new EffectiveValueEntry(); entry.BaseValueSourceInternal = BaseValueSourceInternal; entry.PropertyIndex = PropertyIndex; entry.IsDeferredReference = IsDeferredReference; // If the property has a modifier return the modified value Debug.Assert(ModifiedValue != null); // outside of DO, we flatten modified value ModifiedValue modifiedValue = ModifiedValue; // Note that the modified values have an order of precedence // 1. Coerced Value (including Current value) // 2. Animated Value // 3. Expression Value // Also note that we support any arbitrary combinations of these // modifiers and will yet the precedence metioned above. if (IsCoerced) { if ((requests & RequestFlags.CoercionBaseValue) == 0) { entry.Value = modifiedValue.CoercedValue; } else { // This is the case when CoerceValue tries to query // the old base value for the property if (IsCoercedWithCurrentValue) { entry.Value = modifiedValue.CoercedValue; } else if (IsAnimated && ((requests & RequestFlags.AnimationBaseValue) == 0)) { entry.Value = modifiedValue.AnimatedValue; } else if (IsExpression) { entry.Value = modifiedValue.ExpressionValue; } else { entry.Value = modifiedValue.BaseValue; } } } else if (IsAnimated) { if ((requests & RequestFlags.AnimationBaseValue) == 0) { entry.Value = modifiedValue.AnimatedValue; } else { // This is the case when [UI/Content]Element are // requesting the base value of an animation. if (IsExpression) { entry.Value = modifiedValue.ExpressionValue; } else { entry.Value = modifiedValue.BaseValue; } } } else { Debug.Assert(IsExpression == true); object expressionValue = modifiedValue.ExpressionValue; entry.Value = expressionValue; } Debug.Assert(entry.IsDeferredReference == (entry.Value is DeferredReference), "Value and DeferredReference flag should be in [....]; hitting this may mean that it's time to divide the DeferredReference flag into a set of flags, one for each modifier"); return(entry); }
private void ProcessCoerceValue( DependencyProperty dp, PropertyMetadata metadata, ref EntryIndex entryIndex, ref int targetIndex, ref EffectiveValueEntry newEntry, ref EffectiveValueEntry oldEntry, ref object oldValue, object baseValue, object controlValue, CoerceValueCallback coerceValueCallback, bool coerceWithDeferredReference, bool coerceWithCurrentValue, bool skipBaseValueChecks) { if (newEntry.IsDeferredReference) { Debug.Assert(!(newEntry.IsCoerced && !newEntry.IsCoercedWithCurrentValue) && !newEntry.IsAnimated, "Coerced or Animated value cannot be a deferred reference"); // Allow values to stay deferred through coercion callbacks in // limited circumstances, when we know the listener is internal. // Since we never assign DeferredReference instances to // non-internal (non-friend assembly) classes, it's safe to skip // the dereference if the callback is to the DP owner (and not // a derived type). This is consistent with passing raw // DeferredReference instances to ValidateValue callbacks, which // only ever go to the owner class. if (!coerceWithDeferredReference || dp.OwnerType != metadata.CoerceValueCallback.Method.DeclaringType) // Need 2nd check to rule out derived class callback overrides. { // Resolve deferred references because we need the actual // baseValue to evaluate the correct animated value. This is done // by invoking GetValue for this property. DeferredReference dr = (DeferredReference) baseValue; baseValue = dr.GetValue(newEntry.BaseValueSourceInternal); // Set the baseValue back into the entry newEntry.SetCoersionBaseValue(baseValue); entryIndex = CheckEntryIndex(entryIndex, targetIndex); } } object coercedValue = coerceWithCurrentValue ? controlValue : coerceValueCallback(this, baseValue); // Make sure that the call out did not cause a change to entryIndex entryIndex = CheckEntryIndex(entryIndex, targetIndex); // Even if we used the controlValue in the coerce callback, we still want to compare against the original baseValue // to determine if we need to set a coerced value. if (!Equals(dp, coercedValue, baseValue)) { // returning DependencyProperty.UnsetValue from a Coercion callback means "don't do the set" ... // or "use previous value" if (coercedValue == DependencyProperty.UnsetValue) { if (oldEntry.IsDeferredReference) { DeferredReference reference = (DeferredReference)oldValue; oldValue = reference.GetValue(oldEntry.BaseValueSourceInternal); entryIndex = CheckEntryIndex(entryIndex, targetIndex); } coercedValue = oldValue; } // Note that we do not support the value being coerced to a // DeferredReference if (!dp.IsValidValue(coercedValue)) { // well... unless it's the control's "current value" if (!(coerceWithCurrentValue && coercedValue is DeferredReference)) throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, coercedValue, dp.Name)); } // Set the coerced value here. All other values would // have been set during EvaluateEffectiveValue/GetValueCore. newEntry.SetCoercedValue(coercedValue, baseValue, skipBaseValueChecks, coerceWithCurrentValue); } }
/// <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); }
private EffectiveValueEntry EvaluateExpression( EntryIndex entryIndex, DependencyProperty dp, Expression expr, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry) { object value = expr.GetValue(this, dp); bool isDeferredReference = false; if (value != DependencyProperty.UnsetValue && value != Expression.NoValue) { isDeferredReference = (value is DeferredReference); if (!isDeferredReference && !dp.IsValidValue(value)) { #region EventTracing #if VERBOSE_PROPERTY_EVENT if (isDynamicTracing) { if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) { EventTrace.EventProvider.TraceEvent(EventTrace.PROPERTYGUID, MS.Utility.EventType.EndEvent, EventTrace.PROPERTYVALIDATION, 0xFFF ); } } #endif #endregion EventTracing throw new InvalidOperationException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name)); } } else { if (value == Expression.NoValue) { // The expression wants to "hide". First set the // expression value to NoValue to indicate "hiding". newEntry.SetExpressionValue(Expression.NoValue, expr); // Next, get the expression value some other way. if (!dp.ReadOnly) { EvaluateBaseValueCore(dp, metadata, ref newEntry); value = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved).Value; } else { value = DependencyProperty.UnsetValue; } } // if there is still no value, use the default if (value == DependencyProperty.UnsetValue) { value = metadata.GetDefaultValue(this, dp); } } // Set the expr and its evaluated value into // the _effectiveValues cache newEntry.SetExpressionValue(value, expr); return newEntry; }
// 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); }
[FriendAccessAllowed] // Built into Base, also used by Core. internal EffectiveValueEntry GetValueEntry( EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, RequestFlags requests) { EffectiveValueEntry entry; if (dp.ReadOnly) { if (metadata == null) { metadata = dp.GetMetadata(DependencyObjectType); } GetReadOnlyValueCallback getValueCallback = metadata.GetReadOnlyValueCallback; if (getValueCallback != null) { BaseValueSourceInternal valueSource; entry = new EffectiveValueEntry(dp); entry.Value = getValueCallback(this, out valueSource); entry.BaseValueSourceInternal = valueSource; return entry; } } if (entryIndex.Found) { if ((requests & RequestFlags.RawEntry) != 0) { entry = _effectiveValues[entryIndex.Index]; } else { entry = GetEffectiveValue( entryIndex, dp, requests); } } else { entry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Unknown); } if (entry.Value == DependencyProperty.UnsetValue) { if (dp.IsPotentiallyInherited) { if (metadata == null) { metadata = dp.GetMetadata(DependencyObjectType); } if (metadata.IsInherited) { DependencyObject inheritanceParent = InheritanceParent; if (inheritanceParent != null) { entryIndex = inheritanceParent.LookupEntry(dp.GlobalIndex); if (entryIndex.Found) { entry = inheritanceParent.GetEffectiveValue( entryIndex, dp, requests & RequestFlags.DeferredReferences); entry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } } } if (entry.Value != DependencyProperty.UnsetValue) { return entry; } } if ((requests & RequestFlags.SkipDefault) == 0) { if (dp.IsPotentiallyUsingDefaultValueFactory) { if (metadata == null) { metadata = dp.GetMetadata(DependencyObjectType); } if (((requests & (RequestFlags.DeferredReferences | RequestFlags.RawEntry)) != 0) && metadata.UsingDefaultValueFactory) { entry.BaseValueSourceInternal = BaseValueSourceInternal.Default; entry.Value = new DeferredMutableDefaultReference(metadata, this, dp); return entry; } } else if (!dp.IsDefaultValueChanged) { return EffectiveValueEntry.CreateDefaultValueEntry(dp, dp.DefaultMetadata.DefaultValue); } if (metadata == null) { metadata = dp.GetMetadata(DependencyObjectType); } return EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); } } return entry; }
// // 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); }
[FriendAccessAllowed] // Built into Base, also used by Core and Framework. internal void EndPropertyInitialization() { IsInPropertyInitialization = false; if (_effectiveValues != null) { uint effectiveValuesCount = EffectiveValuesCount; if (effectiveValuesCount != 0) { uint endLength = effectiveValuesCount; if (((float) endLength / (float) _effectiveValues.Length) < 0.8) { // For thread-safety, sealed DOs can't modify _effectiveValues. Debug.Assert(!DO_Sealed, "A Sealed DO cannot be modified"); EffectiveValueEntry[] destEntries = new EffectiveValueEntry[endLength]; Array.Copy(_effectiveValues, 0, destEntries, 0, effectiveValuesCount); _effectiveValues = destEntries; } } } }
/// <summary> /// Allows subclasses to participate in property base value computation /// </summary> /// <param name="dp">Dependency property</param> /// <param name="metadata">Type metadata of the property for the type</param> /// <param name="newEntry">entry computed by base</param> internal sealed override void EvaluateBaseValueCore( DependencyProperty dp, PropertyMetadata metadata, ref EffectiveValueEntry newEntry) { if (dp == StyleProperty) { // If this is the first time that the StyleProperty // is being fetched then mark it such HasStyleEverBeenFetched = true; // Clear the flags associated with the StyleProperty HasImplicitStyleFromResources = false; IsStyleSetFromGenerator = false; } GetRawValue(dp, metadata, ref newEntry); Storyboard.GetComplexPathValue(this, dp, ref newEntry, metadata); }
internal void SetEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry newEntry, EffectiveValueEntry oldEntry) { if (metadata != null && metadata.IsInherited && (newEntry.BaseValueSourceInternal != BaseValueSourceInternal.Inherited || newEntry.IsCoerced || newEntry.IsAnimated) && !IsSelfInheritanceParent) { SetIsSelfInheritanceParent(); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } bool restoreMarker = false; if (oldEntry.HasExpressionMarker && !newEntry.HasExpressionMarker) { BaseValueSourceInternal valueSource = newEntry.BaseValueSourceInternal; restoreMarker = (valueSource == BaseValueSourceInternal.ThemeStyle || valueSource == BaseValueSourceInternal.ThemeStyleTrigger || valueSource == BaseValueSourceInternal.Style || valueSource == BaseValueSourceInternal.TemplateTrigger || valueSource == BaseValueSourceInternal.StyleTrigger || valueSource == BaseValueSourceInternal.ParentTemplate || valueSource == BaseValueSourceInternal.ParentTemplateTrigger); } if (restoreMarker) { newEntry.RestoreExpressionMarker(); } else if (oldEntry.IsExpression && oldEntry.ModifiedValue.ExpressionValue == Expression.NoValue) { // we now have a value for an expression that is "hiding" - save it // as the expression value newEntry.SetExpressionValue(newEntry.Value, oldEntry.ModifiedValue.BaseValue); } #if DEBUG object baseValue; if (!newEntry.HasModifiers) { baseValue = newEntry.Value; } else { if (newEntry.IsCoercedWithCurrentValue) { baseValue = newEntry.ModifiedValue.CoercedValue; } else if (newEntry.IsExpression) { baseValue = newEntry.ModifiedValue.ExpressionValue; } else { baseValue = newEntry.ModifiedValue.BaseValue; } } Debug.Assert(newEntry.IsDeferredReference == (baseValue is DeferredReference)); #endif if (entryIndex.Found) { _effectiveValues[entryIndex.Index] = newEntry; } else { InsertEntry(newEntry, entryIndex.Index); if (metadata != null && metadata.IsInherited) { InheritableEffectiveValuesCount++; } } Debug.Assert(dp == null || (dp.GlobalIndex == newEntry.PropertyIndex), "EffectiveValueEntry & DependencyProperty do not match"); }
//[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 internal void GetRawValue(DependencyProperty dp, PropertyMetadata metadata, ref EffectiveValueEntry entry) { // Check if value was resolved by base. If so, run it by animations if ((entry.BaseValueSourceInternal == BaseValueSourceInternal.Local) && (entry.GetFlattenedEntry(RequestFlags.FullyResolved).Value != DependencyProperty.UnsetValue)) { return; } // // Try for container Style driven value // if (TemplateChildIndex != -1) { // This instance is in the template child chain of a Template.VisualTree, // so we need to see if the Style has an applicable value. // // If the parent element's style is changing, this instance is // in a visual tree that is being removed, and the value request // is simply a result of tearing down some information in that // tree (e.g. a BindingExpression). If so, just pretend there is no style (bug 991395). if (GetValueFromTemplatedParent(dp, ref entry)) { return; } } // // Try for Styled value // // Here are some of the implicit rules used by GetRawValue, // while querying properties on the container. // 1. Style property cannot be specified in a Style // 2. Style property cannot be specified in a ThemeStyle // 3. Style property cannot be specified in a Template // 4. DefaultStyleKey property cannot be specified in a ThemeStyle // 5. DefaultStyleKey property cannot be specified in a Template // 6. Template property cannot be specified in a Template if (dp != StyleProperty) { if (StyleHelper.GetValueFromStyleOrTemplate(new FrameworkObject(null, this), dp, ref entry)) { return; } } else { object source; object implicitValue = FrameworkElement.FindImplicitStyleResource(this, this.GetType(), out source); if (implicitValue != DependencyProperty.UnsetValue) { // Commented this because the implicit fetch could also return a DeferredDictionaryReference // if (!(implicitValue is Style)) // { // throw new InvalidOperationException(SR.Get(SRID.InvalidImplicitStyleResource, this.GetType().Name, implicitValue)); // } // This style has been fetched from resources HasImplicitStyleFromResources = true; entry.BaseValueSourceInternal = BaseValueSourceInternal.ImplicitReference; entry.Value = implicitValue; return; } } // // Try for Inherited value // FrameworkPropertyMetadata fmetadata = metadata as FrameworkPropertyMetadata; // Note that for inheritable properties that override the default value a parent can impart // its default value to the child even though the property may not have been set locally or // via a style or template (ie. IsUsed flag would be false). if (fmetadata != null) { if (fmetadata.Inherits) { // // Inheritance // if (!TreeWalkHelper.SkipNext(InheritanceBehavior) || fmetadata.OverridesInheritanceBehavior == true) { // Used to terminate tree walk if a tree boundary is hit InheritanceBehavior inheritanceBehavior; FrameworkContentElement parentFCE; FrameworkElement parentFE; bool hasParent = FrameworkElement.GetFrameworkParent(this, out parentFE, out parentFCE); while (hasParent) { bool inheritanceNode; if (parentFE != null) { inheritanceNode = TreeWalkHelper.IsInheritanceNode(parentFE, dp, out inheritanceBehavior); } else // (parentFCE != null) { inheritanceNode = TreeWalkHelper.IsInheritanceNode(parentFCE, dp, out inheritanceBehavior); } // If the current node has SkipNow semantics then we do // not need to lookup the inheritable value on it. if (TreeWalkHelper.SkipNow(inheritanceBehavior)) { break; } // Check if node is an inheritance node, if so, query it if (inheritanceNode) { #region EventTracing if (EventTrace.IsEnabled(EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Verbose)) { string TypeAndName = "[" + GetType().Name + "]" + dp.Name; EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientPropParentCheck, EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Verbose, GetHashCode(), TypeAndName); } #endregion EventTracing DependencyObject parentDO = parentFE; if (parentDO == null) { parentDO = parentFCE; } EntryIndex entryIndex = parentDO.LookupEntry(dp.GlobalIndex); entry = parentDO.GetValueEntry( entryIndex, dp, fmetadata, RequestFlags.SkipDefault | RequestFlags.DeferredReferences); if (entry.Value != DependencyProperty.UnsetValue) { entry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } return; } // If the current node has SkipNext semantics then we do // not need to lookup the inheritable value on its parent. if (TreeWalkHelper.SkipNext(inheritanceBehavior)) { break; } // No boundary or inheritance node found, continue search if (parentFE != null) { hasParent = FrameworkElement.GetFrameworkParent(parentFE, out parentFE, out parentFCE); } else { hasParent = FrameworkElement.GetFrameworkParent(parentFCE, out parentFE, out parentFCE); } } } } } // No value found. Debug.Assert(entry.Value == DependencyProperty.UnsetValue); }
/// <summary> /// The common code shared by all variants of SetValue /// </summary> // Takes metadata from caller because most of them have already retrieved it // for their own purposes, avoiding the duplicate GetMetadata call. private void SetValueCommon( DependencyProperty dp, object value, PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, OperationType operationType, bool isInternal) { if (IsSealed) { throw new InvalidOperationException(SR.Get(SRID.SetOnReadOnlyObjectNotAllowed, this)); } Expression newExpr = null; DependencySource[] newSources = null; EntryIndex entryIndex = LookupEntry(dp.GlobalIndex); // Treat Unset as a Clear if( value == DependencyProperty.UnsetValue ) { // Parameters should have already been validated, so we call // into the private method to avoid validating again. ClearValueCommon(entryIndex, dp, metadata); return; } // Validate the "value" against the DP. bool isDeferredReference = false; bool newValueHasExpressionMarker = (value == ExpressionInAlternativeStore); // First try to validate the value; only after this validation fails should we // do the more expensive checks (type checks) for the less common scenarios if (!newValueHasExpressionMarker) { bool isValidValue = isInternal ? dp.IsValidValueInternal(value) : dp.IsValidValue(value); // for properties of type "object", we have to always check for expression & deferredreference if (!isValidValue || dp.IsObjectType) { // 2nd most common is expression newExpr = value as Expression; if (newExpr != null) { // For Expressions, perform additional validation // Make sure Expression is "attachable" if (!newExpr.Attachable) { throw new ArgumentException(SR.Get(SRID.SharingNonSharableExpression)); } // Check dispatchers of all Sources // CALLBACK newSources = newExpr.GetSources(); ValidateSources(this, newSources, newExpr); } else { // and least common is DeferredReference isDeferredReference = (value is DeferredReference); if (!isDeferredReference) { if (!isValidValue) { // it's not a valid value & it's not an expression, so throw throw new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name)); } } } } } // Get old value EffectiveValueEntry oldEntry; if (operationType == OperationType.ChangeMutableDefaultValue) { oldEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default); oldEntry.Value = value; } else { oldEntry = GetValueEntry(entryIndex, dp, metadata, RequestFlags.RawEntry); } // if there's an expression in some other store, fetch it now Expression currentExpr = (oldEntry.HasExpressionMarker) ? _getExpressionCore(this, dp, metadata) : (oldEntry.IsExpression) ? (oldEntry.LocalValue as Expression) : null; // Allow expression to store value if new value is // not an Expression, if applicable bool handled = false; if ((currentExpr != null) && (newExpr == null)) { // Resolve deferred references because we haven't modified // the expression code to work with DeferredReference yet. if (isDeferredReference) { value = ((DeferredReference) value).GetValue(BaseValueSourceInternal.Local); } // CALLBACK handled = currentExpr.SetValue(this, dp, value); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } // Create the new effective value entry EffectiveValueEntry newEntry; if (handled) { // If expression handled set, then done if (entryIndex.Found) { newEntry = _effectiveValues[entryIndex.Index]; } else { // the expression.SetValue resulted in this value being removed from the table; // use the default value. newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp)); } coerceWithCurrentValue = false; // expression already handled the control-value } else { // allow a control-value to coerce an expression value, when the // expression didn't handle the value if (coerceWithCurrentValue && currentExpr != null) { currentExpr = null; } newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local); // detach the old expression, if applicable if (currentExpr != null) { // CALLBACK DependencySource[] currentSources = currentExpr.GetSources(); UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false); // Remove // CALLBACK currentExpr.OnDetach(this, dp); currentExpr.MarkDetached(); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } // attach the new expression, if applicable if (newExpr == null) { // simple local value set newEntry.HasExpressionMarker = newValueHasExpressionMarker; newEntry.Value = value; } else { Debug.Assert(!coerceWithCurrentValue, "Expression values not supported in SetCurrentValue"); // First put the expression in the effectivevalueentry table for this object; // this allows the expression to update the value accordingly in OnAttach SetEffectiveValue(entryIndex, dp, dp.GlobalIndex, metadata, newExpr, BaseValueSourceInternal.Local); // Before the expression is attached it has default value object defaultValue = metadata.GetDefaultValue(this, dp); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); SetExpressionValue(entryIndex, defaultValue, newExpr); UpdateSourceDependentLists(this, dp, newSources, newExpr, true); // Add newExpr.MarkAttached(); // CALLBACK newExpr.OnAttach(this, dp); // the attach may have added entries in the effective value table ... // so, update the entryIndex accordingly. entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); newEntry = EvaluateExpression( entryIndex, dp, newExpr, metadata, oldEntry, _effectiveValues[entryIndex.Index]); entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex); } } UpdateEffectiveValue( entryIndex, dp, metadata, oldEntry, ref newEntry, coerceWithDeferredReference, coerceWithCurrentValue, operationType); }
// This FrameworkElement has been established to be a Template.VisualTree // node of a parent object. Ask the TemplatedParent's Style object if // they have a value for us. private bool GetValueFromTemplatedParent(DependencyProperty dp, ref EffectiveValueEntry entry) { FrameworkTemplate frameworkTemplate = null; FrameworkElement feTemplatedParent = (FrameworkElement)_templatedParent; frameworkTemplate = feTemplatedParent.TemplateInternal; if (frameworkTemplate != null) { return StyleHelper.GetValueFromTemplatedParent( _templatedParent, TemplateChildIndex, new FrameworkObject(null, this), dp, ref frameworkTemplate.ChildRecordFromChildIndex, frameworkTemplate.VisualTree, ref entry); } return false; }
/// <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; }
// Like GetValueCore, except it returns the expression (if any) instead of its value internal Expression GetExpressionCore(DependencyProperty dp, PropertyMetadata metadata) { this.IsRequestingExpression = true; EffectiveValueEntry entry = new EffectiveValueEntry(dp); entry.Value = DependencyProperty.UnsetValue; this.EvaluateBaseValueCore(dp, metadata, ref entry); this.IsRequestingExpression = false; return entry.Value as Expression; }
// // 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> /// Notification that a specified property has been changed /// </summary> /// <param name="e">EventArgs that contains the property, metadata, old value, and new value for this change</param> protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { DependencyProperty dp = e.Property; base.OnPropertyChanged(e); if (e.IsAValueChange || e.IsASubPropertyChange) { // // Try to fire the Loaded event on the root of the tree // because for this case the OnParentChanged will not // have a chance to fire the Loaded event. // if (dp != null && dp.OwnerType == typeof(PresentationSource) && dp.Name == "RootSource") { TryFireInitialized(); } if (dp == FrameworkElement.NameProperty && EventTrace.IsEnabled(EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Verbose)) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.PerfElementIDName, EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Verbose, PerfService.GetPerfElementID(this), GetType().Name, GetValue(dp)); } // // Invalidation propagation for Styles // // Regardless of metadata, the Style/DefaultStyleKey properties are never a trigger drivers if (dp != StyleProperty && dp != DefaultStyleKeyProperty) { // Note even properties on non-container nodes within a template could be driving a trigger if (TemplatedParent != null) { FrameworkElement feTemplatedParent = TemplatedParent as FrameworkElement; FrameworkTemplate frameworkTemplate = feTemplatedParent.TemplateInternal; StyleHelper.OnTriggerSourcePropertyInvalidated(null, frameworkTemplate, TemplatedParent, dp, e, false /*invalidateOnlyContainer*/, ref frameworkTemplate.TriggerSourceRecordFromChildIndex, ref frameworkTemplate.PropertyTriggersWithActions, TemplateChildIndex /*sourceChildIndex*/); } // Do not validate Style during an invalidation if the Style was // never used before (dependents do not need invalidation) if (Style != null) { StyleHelper.OnTriggerSourcePropertyInvalidated(Style, null, this, dp, e, true /*invalidateOnlyContainer*/, ref Style.TriggerSourceRecordFromChildIndex, ref Style.PropertyTriggersWithActions, 0 /*sourceChildId*/); // Style can only have triggers that are driven by properties on the container } // Do not validate Template during an invalidation if the Template was // never used before (dependents do not need invalidation) // There may be container dependents in the ThemeStyle. Invalidate them. if (ThemeStyle != null && Style != ThemeStyle) { StyleHelper.OnTriggerSourcePropertyInvalidated(ThemeStyle, null, this, dp, e, true /*invalidateOnlyContainer*/, ref ThemeStyle.TriggerSourceRecordFromChildIndex, ref ThemeStyle.PropertyTriggersWithActions, 0 /*sourceChildIndex*/); // ThemeStyle can only have triggers that are driven by properties on the container } } } FrameworkPropertyMetadata fmetadata = e.Metadata as FrameworkPropertyMetadata; // // Invalidation propagation for Groups and Inheritance // // Metadata must exist specifically stating propagate invalidation // due to group or inheritance if (fmetadata != null) { // // Inheritance // if (fmetadata.Inherits) { // Invalidate Inheritable descendents only if instance is not a TreeSeparator // or fmetadata.OverridesInheritanceBehavior is set to override separated tree behavior if ((InheritanceBehavior == InheritanceBehavior.Default || fmetadata.OverridesInheritanceBehavior) && (!DependencyObject.IsTreeWalkOperation(e.OperationType) || PotentiallyHasMentees)) { EffectiveValueEntry newEntry = e.NewEntry; EffectiveValueEntry oldEntry = e.OldEntry; if (oldEntry.BaseValueSourceInternal > newEntry.BaseValueSourceInternal) { // valuesource == Inherited && value == UnsetValue indicates that we are clearing the inherited value newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Inherited); } else { newEntry = newEntry.GetFlattenedEntry(RequestFlags.FullyResolved); newEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } if (oldEntry.BaseValueSourceInternal != BaseValueSourceInternal.Default || oldEntry.HasModifiers) { oldEntry = oldEntry.GetFlattenedEntry(RequestFlags.FullyResolved); oldEntry.BaseValueSourceInternal = BaseValueSourceInternal.Inherited; } else { // we use an empty EffectiveValueEntry as a signal that the old entry was the default value oldEntry = new EffectiveValueEntry(); } InheritablePropertyChangeInfo info = new InheritablePropertyChangeInfo( dp, oldEntry, newEntry); // Don't InvalidateTree if we're in the middle of doing it. if (!DependencyObject.IsTreeWalkOperation(e.OperationType)) { TreeWalkHelper.InvalidateOnInheritablePropertyChange(null, this, info, true); } // Notify mentees if they exist if (PotentiallyHasMentees) { TreeWalkHelper.OnInheritedPropertyChanged(this, ref info, InheritanceBehavior); } } } } }