Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / System / Windows / PropertyMetadata.cs / 1305600 / PropertyMetadata.cs
using MS.Internal; using MS.Utility; using System; using System.Diagnostics; using System.Collections.Generic; using System.Collections; using System.Windows.Threading; // for DispatcherObject using MS.Internal.WindowsBase; namespace System.Windows { ////// Type-specific property metadata /// public class PropertyMetadata { ////// Type metadata construction /// public PropertyMetadata() { } ////// Type metadata construction /// /// Default value of property public PropertyMetadata(object defaultValue) { DefaultValue = defaultValue; } ////// Type meta construction /// /// Called when the property has been changed public PropertyMetadata(PropertyChangedCallback propertyChangedCallback) { PropertyChangedCallback = propertyChangedCallback; } ////// Type meta construction /// /// Default value of property /// Called when the property has been changed public PropertyMetadata(object defaultValue, PropertyChangedCallback propertyChangedCallback) { DefaultValue = defaultValue; PropertyChangedCallback = propertyChangedCallback; } ////// Type meta construction /// /// Default value of property /// Called when the property has been changed /// Called on update of value public PropertyMetadata(object defaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback) { DefaultValue = defaultValue; PropertyChangedCallback = propertyChangedCallback; CoerceValueCallback = coerceValueCallback; } // ////// Default value of property /// public object DefaultValue { get { DefaultValueFactory defaultFactory = _defaultValue as DefaultValueFactory; if (defaultFactory == null) { return _defaultValue; } else { return defaultFactory.DefaultValue; } } set { if (Sealed) { throw new InvalidOperationException(SR.Get(SRID.TypeMetadataCannotChangeAfterUse)); } if (value == DependencyProperty.UnsetValue) { throw new ArgumentException(SR.Get(SRID.DefaultValueMayNotBeUnset)); } _defaultValue = value; SetModified(MetadataFlags.DefaultValueModifiedID); } } // ////// Returns true if the default value is a DefaultValueFactory /// internal bool UsingDefaultValueFactory { get { return _defaultValue is DefaultValueFactory; } } // ////// GetDefaultValue returns the default value for a given owner and property. /// If the default value is a DefaultValueFactory it will instantiate and cache /// the default value on the object. It must never return an unfrozen default /// value if the owner is a frozen Freezable. /// /// /// ///[FriendAccessAllowed] // Built into Base, also used by Framework. internal object GetDefaultValue(DependencyObject owner, DependencyProperty property) { Debug.Assert(owner != null && property != null, "Caller must provide owner and property or this method will throw in the event of a cache miss."); // If we are not using a DefaultValueFactory (common case) // just return _defaultValue DefaultValueFactory defaultFactory = _defaultValue as DefaultValueFactory; if (defaultFactory == null) { return _defaultValue; } // If the owner is Sealed it must not have a cached Freezable default value, // regardless of whether or not the owner is a Freezable. The reason // for this is that a default created using the FreezableDefaultValueFactory // will attempt to set itself as a local value if it is changed. Since the owner // is Sealed this will throw an exception. // // The solution to this if the owner is a Freezable is to toss out all cached // default values when we Seal. If the owner is not a Freezable we'll promote // the value to locally cached. Either way no Sealed DO can have a cached // default value, so we'll return the frozen default value instead. if (owner.IsSealed) { return defaultFactory.DefaultValue; } // See if we already have a valid default value that was // created by a prior call to GetDefaultValue. object result = GetCachedDefaultValue(owner, property); if (result != DependencyProperty.UnsetValue) { // When sealing a DO we toss out all the cached values (see DependencyObject.Seal()). // We technically only need to throw out cached values created via the // FreezableDefaultValueFactory, but it's more consistent this way. Debug.Assert(!owner.IsSealed, "If the owner is Sealed we should not have a cached default value"); return result; } // Otherwise we need to invoke the factory to create the DefaultValue // for this property. result = defaultFactory.CreateDefaultValue(owner, property); // Default value validation ensures that default values do not have // thread affinity. This is because a default value is typically // stored in the shared property metadata and handed out to all // instances of the owning DependencyObject type. // // DefaultValueFactory.CreateDefaultValue ensures that the default // value has thread-affinity to the current thread. We can thus // skip that portion of the default value validation by calling // ValidateFactoryDefaultValue. Debug.Assert(!(result is DispatcherObject) || ((DispatcherObject)result).Dispatcher == owner.Dispatcher); property.ValidateFactoryDefaultValue(result); // Cache the created DefaultValue so that we can consistently hand // out the same default each time we are asked. SetCachedDefaultValue(owner, property, result); return result; } // Because the frugalmap is going to be stored in an uncommon field, it would get boxed // to avoid this boxing, skip the struct and go straight for the class contained by the // struct. Given the simplicity of this scenario, we can get away with this. private object GetCachedDefaultValue(DependencyObject owner, DependencyProperty property) { FrugalMapBase map = _defaultValueFactoryCache.GetValue(owner); if (map == null) { return DependencyProperty.UnsetValue; } return map.Search(property.GlobalIndex); } private void SetCachedDefaultValue(DependencyObject owner, DependencyProperty property, object value) { FrugalMapBase map = _defaultValueFactoryCache.GetValue(owner); if (map == null) { map = new SingleObjectMap(); _defaultValueFactoryCache.SetValue(owner, map); } else if (!(map is HashObjectMap)) { FrugalMapBase newMap = new HashObjectMap(); map.Promote(newMap); map = newMap; _defaultValueFactoryCache.SetValue(owner, map); } map.InsertEntry(property.GlobalIndex, value); } /// /// This method causes the DefaultValue cache to be cleared ensuring /// that CreateDefaultValue will be called next time this metadata /// is asked to participate in the DefaultValue factory pattern. /// /// This is internal so it can be accessed by subclasses of /// DefaultValueFactory. /// internal void ClearCachedDefaultValue(DependencyObject owner, DependencyProperty property) { FrugalMapBase map = _defaultValueFactoryCache.GetValue(owner); if (map.Count == 1) { _defaultValueFactoryCache.ClearValue(owner); } else { map.RemoveEntry(property.GlobalIndex); } } internal static void PromoteAllCachedDefaultValues(DependencyObject owner) { FrugalMapBase map = _defaultValueFactoryCache.GetValue(owner); if (map != null) { // Iterate through all the items in the map (each representing a DP) // and promote them to locally-set. map.Iterate(null, _promotionCallback); } } ////// Removes all cached default values on an object. It iterates though /// each one and, if the cached default is a Freezable, removes its /// Changed event handlers. This is called by DependencyObject.Seal() /// for Freezable type owners. /// /// internal static void RemoveAllCachedDefaultValues(Freezable owner) { FrugalMapBase map = _defaultValueFactoryCache.GetValue(owner); if (map != null) { // Iterate through all the items in the map (each representing a DP) // and remove the promotion handlers map.Iterate(null, _removalCallback); // Now that they're all clear remove the map. _defaultValueFactoryCache.ClearValue(owner); } } ////// Called once per iteration through the FrugalMap containing all cached default values /// for a given DependencyObject. This method removes the promotion handlers on each cached /// default and freezes it. /// /// /// The DP's global index /// The cached default private static void DefaultValueCacheRemovalCallback(ArrayList list, int key, object value) { Freezable cachedDefault = value as Freezable; if (cachedDefault != null) { // Freeze fires the Changed event so we need to clear off the handlers before // calling it. Otherwise the promoter would run and attempt to set the // cached default as a local value. cachedDefault.ClearContextAndHandlers(); cachedDefault.Freeze(); } } ////// Called once per iteration through the FrugalMap containing all cached default values /// for a given DependencyObject. This method promotes each of the defaults to locally-set. /// /// /// The DP's global index /// The cached default private static void DefaultValueCachePromotionCallback(ArrayList list, int key, object value) { Freezable cachedDefault = value as Freezable; if (cachedDefault != null) { // The only way to promote a cached default is to fire its Changed event. cachedDefault.FireChanged(); } } ////// Whether the DefaultValue was explictly set - needed to know if the /// value should be used in Register. /// internal bool DefaultValueWasSet() { return IsModified(MetadataFlags.DefaultValueModifiedID); } ////// Property changed callback /// public PropertyChangedCallback PropertyChangedCallback { get { return _propertyChangedCallback; } set { if (Sealed) { throw new InvalidOperationException(SR.Get(SRID.TypeMetadataCannotChangeAfterUse)); } _propertyChangedCallback = value; } } ////// Specialized callback invoked upon a call to UpdateValue /// ////// Used for "coercing" effective property value without actually subclassing /// public CoerceValueCallback CoerceValueCallback { get { return _coerceValueCallback; } set { if (Sealed) { throw new InvalidOperationException(SR.Get(SRID.TypeMetadataCannotChangeAfterUse)); } _coerceValueCallback = value; } } ////// Specialized callback for remote storage of value for read-only properties /// ////// This is used exclusively by FrameworkElement.ActualWidth and ActualHeight to save 48 bytes /// of state per FrameworkElement. /// [FriendAccessAllowed] // Built into Base, also used by Framework. internal virtual GetReadOnlyValueCallback GetReadOnlyValueCallback { get { return null; } } ////// Specialized callback invoked for each property when a Freezable /// object is frozen. /// ////// Used to provide specialized behavior when freezing an object /// that a property has been set on. This callback can be used to /// decide whether to do a "deep" freeze, a "shallow" freeze, to /// fail the freeze attempt, etc. /// [FriendAccessAllowed] // Currently used by Storyboard in PresentationFramework. internal FreezeValueCallback FreezeValueCallback { get { if(_freezeValueCallback != null) { return _freezeValueCallback; } else { return _defaultFreezeValueCallback; } } set { if (Sealed) { throw new InvalidOperationException(SR.Get(SRID.TypeMetadataCannotChangeAfterUse)); } _freezeValueCallback = value; } } 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; } private static FreezeValueCallback _defaultFreezeValueCallback = DefaultFreezeValueCallback; ////// Creates a new instance of this property metadata. This method is used /// when metadata needs to be cloned. After CreateInstance is called the /// framework will call Merge to merge metadata into the new instance. /// Deriving classes must override this and return a new instance of /// themselves. /// internal virtual PropertyMetadata CreateInstance() { return new PropertyMetadata(); } // // Returns a copy of this property metadata by calling CreateInstance // and then Merge // internal PropertyMetadata Copy(DependencyProperty dp) { PropertyMetadata newMetadata = CreateInstance(); newMetadata.InvokeMerge(this, dp); return newMetadata; } ////// Merge set source state into this /// ////// Used when overriding metadata /// /// Base metadata to merge /// DependencyProperty that this metadata is being applied to protected virtual void Merge(PropertyMetadata baseMetadata, DependencyProperty dp) { if (baseMetadata == null) { throw new ArgumentNullException("baseMetadata"); } if (Sealed) { throw new InvalidOperationException(SR.Get(SRID.TypeMetadataCannotChangeAfterUse)); } // Merge source metadata into this // Take source default if this default was never set if (!IsModified(MetadataFlags.DefaultValueModifiedID)) { _defaultValue = baseMetadata.DefaultValue; } if (baseMetadata.PropertyChangedCallback != null) { // All delegates are MulticastDelegate. Non-multicast "Delegate" // was designed and is documented in MSDN. But for all practical // purposes, it was actually cut before v1.0 of the CLR shipped. // Build the handler list such that handlers added // via OverrideMetadata are called last (base invocation first) Delegate[] handlers = baseMetadata.PropertyChangedCallback.GetInvocationList(); if (handlers.Length > 0) { PropertyChangedCallback headHandler = (PropertyChangedCallback)handlers[0]; for (int i = 1; i < handlers.Length; i++) { headHandler += (PropertyChangedCallback)handlers[i]; } headHandler += _propertyChangedCallback; _propertyChangedCallback = headHandler; } } // if (_coerceValueCallback == null) { _coerceValueCallback = baseMetadata.CoerceValueCallback; } // FreezeValueCallback not combined if (_freezeValueCallback == null) { _freezeValueCallback = baseMetadata.FreezeValueCallback; } } internal void InvokeMerge(PropertyMetadata baseMetadata, DependencyProperty dp) { Merge(baseMetadata, dp); } ////// Notification that this metadata has been applied to a property /// and the metadata is being sealed /// ////// Normally, any mutability of the data structure should be marked /// as immutable at this point /// /// DependencyProperty /// Type associating metadata (null if default metadata) protected virtual void OnApply(DependencyProperty dp, Type targetType) { } ////// Determines if the metadata has been applied to a property resulting /// in the sealing (immutability) of the instance /// protected bool IsSealed { get { return Sealed; } } internal void Seal(DependencyProperty dp, Type targetType) { // CALLBACK OnApply(dp, targetType); Sealed = true; } internal bool IsDefaultValueModified { get { return IsModified(MetadataFlags.DefaultValueModifiedID); } } internal bool IsInherited { get { return (MetadataFlags.Inherited & _flags) != 0;; } set { if (value) { _flags |= MetadataFlags.Inherited; } else { _flags &= (~MetadataFlags.Inherited); } } } private object _defaultValue; private PropertyChangedCallback _propertyChangedCallback; private CoerceValueCallback _coerceValueCallback; private FreezeValueCallback _freezeValueCallback; // [FriendAccessAllowed] // Built into Base, also used by Core and Framework. internal enum MetadataFlags : uint { DefaultValueModifiedID = 0x00000001, SealedID = 0x00000002, // Unused = 0x00000004, // Unused = 0x00000008, Inherited = 0x00000010, UI_IsAnimationProhibitedID = 0x00000020, // True if peer refers to an owner's animation peer property; False if Peer refers to the animation peer's owner property FW_AffectsMeasureID = 0x00000040, FW_AffectsArrangeID = 0x00000080, FW_AffectsParentMeasureID = 0x00000100, FW_AffectsParentArrangeID = 0x00000200, FW_AffectsRenderID = 0x00000400, FW_OverridesInheritanceBehaviorID = 0x00000800, FW_IsNotDataBindableID = 0x00001000, FW_BindsTwoWayByDefaultID = 0x00002000, FW_ShouldBeJournaledID = 0x00004000, FW_SubPropertiesDoNotAffectRenderID = 0x00008000, FW_SubPropertiesDoNotAffectRenderModifiedID = 0x00010000, // Unused = 0x00020000, // Unused = 0x00040000, // Unused = 0x00080000, FW_InheritsModifiedID = 0x00100000, FW_OverridesInheritanceBehaviorModifiedID = 0x00200000, // Unused = 0x00400000, // Unused = 0x00800000, FW_ShouldBeJournaledModifiedID = 0x01000000, FW_UpdatesSourceOnLostFocusByDefaultID = 0x02000000, FW_DefaultUpdateSourceTriggerModifiedID = 0x04000000, FW_ReadOnlyID = 0x08000000, // Unused = 0x10000000, // Unused = 0x20000000, FW_DefaultUpdateSourceTriggerEnumBit1 = 0x40000000, // Must match constants used in FrameworkPropertyMetadata FW_DefaultUpdateSourceTriggerEnumBit2 = 0x80000000, // Must match constants used in FrameworkPropertyMetadata } // PropertyMetadata, UIPropertyMetadata, and FrameworkPropertyMetadata. [FriendAccessAllowed] // Built into Base, also used by Core and Framework. internal MetadataFlags _flags; private void SetModified(MetadataFlags id) { _flags |= id; } private bool IsModified(MetadataFlags id) { return (id & _flags) != 0; } ////// Write a flag value /// [FriendAccessAllowed] // Built into Base, also used by Core and Framework. internal void WriteFlag(MetadataFlags id, bool value) { if (value) { _flags |= id; } else { _flags &= (~id); } } ////// Read a flag value /// [FriendAccessAllowed] // Built into Base, also used by Core and Framework. internal bool ReadFlag(MetadataFlags id) { return (id & _flags) != 0; } internal bool Sealed { [FriendAccessAllowed] // Built into Base, also used by Core. get { return ReadFlag(MetadataFlags.SealedID); } set { WriteFlag(MetadataFlags.SealedID, value); } } // We use this uncommon field to stash values created by our default value factory // in the owner's _localStore. private static readonly UncommonField_defaultValueFactoryCache = new UncommonField (); private static FrugalMapIterationCallback _removalCallback = new FrugalMapIterationCallback(DefaultValueCacheRemovalCallback); private static FrugalMapIterationCallback _promotionCallback = new FrugalMapIterationCallback(DefaultValueCachePromotionCallback); } /// /// GetReadOnlyValueCallback -- a very specialized callback that allows storage for read-only properties /// to be managed outside of the effective value store on a DO. This optimization is restricted to read-only /// properties because read-only properties can only have a value explicitly set by the keeper of the key, so /// it eliminates the possibility of a self-managed store missing modifiers such as expressions, coercion, /// and animation. /// [FriendAccessAllowed] // Built into Base, also used by Framework. internal delegate object GetReadOnlyValueCallback(DependencyObject d, out BaseValueSourceInternal source); } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlSchemaSimpleContent.cs
- PersonalizationProviderCollection.cs
- DocumentGridPage.cs
- CustomValidator.cs
- DataRecordInternal.cs
- CalendarModeChangedEventArgs.cs
- CalendarDesigner.cs
- VersionPair.cs
- GridViewPageEventArgs.cs
- LogStore.cs
- ViewStateModeByIdAttribute.cs
- PathParser.cs
- EventDrivenDesigner.cs
- securitymgrsite.cs
- UInt64.cs
- LayoutTableCell.cs
- LockRecursionException.cs
- IsolatedStorageFilePermission.cs
- FontUnit.cs
- JulianCalendar.cs
- CallbackValidatorAttribute.cs
- ReaderWriterLockWrapper.cs
- XmlBoundElement.cs
- WebPartsPersonalization.cs
- PathFigureCollectionValueSerializer.cs
- AlternateViewCollection.cs
- TemplateBindingExtension.cs
- ParserHooks.cs
- ItemContainerGenerator.cs
- ViewGenerator.cs
- AsymmetricKeyExchangeFormatter.cs
- XmlWrappingWriter.cs
- WorkflowTraceTransfer.cs
- JoinElimination.cs
- Merger.cs
- DataGridTable.cs
- TraceInternal.cs
- XmlCharCheckingReader.cs
- JoinGraph.cs
- DriveNotFoundException.cs
- OSFeature.cs
- CallbackHandler.cs
- UnknownBitmapDecoder.cs
- ClientSponsor.cs
- BuildProvidersCompiler.cs
- EmbeddedMailObjectsCollection.cs
- COAUTHIDENTITY.cs
- FolderBrowserDialog.cs
- EpmCustomContentWriterNodeData.cs
- LinqDataSourceUpdateEventArgs.cs
- StyleModeStack.cs
- XmlDocumentType.cs
- TemplateControlBuildProvider.cs
- PreloadedPackages.cs
- TimeSpanParse.cs
- Geometry.cs
- WorkflowItemsPresenter.cs
- DictionaryItemsCollection.cs
- AddInBase.cs
- UserControlBuildProvider.cs
- ViewCellRelation.cs
- RootBrowserWindowProxy.cs
- RichTextBox.cs
- cryptoapiTransform.cs
- PriorityQueue.cs
- WrappedOptions.cs
- CodeSpit.cs
- ArraySubsetEnumerator.cs
- NonParentingControl.cs
- ScalarRestriction.cs
- commandenforcer.cs
- LambdaExpression.cs
- ConstructorBuilder.cs
- ThreadStateException.cs
- InlinedAggregationOperatorEnumerator.cs
- ScrollData.cs
- WeakEventTable.cs
- MessageDescriptionCollection.cs
- RegexNode.cs
- Bitmap.cs
- MachineKey.cs
- DataStorage.cs
- ClientRolePrincipal.cs
- DelayDesigner.cs
- ResourceContainer.cs
- PersonalizationAdministration.cs
- ChtmlTextWriter.cs
- DataObjectCopyingEventArgs.cs
- LogLogRecordEnumerator.cs
- Transform.cs
- OdbcParameter.cs
- LineBreakRecord.cs
- ButtonChrome.cs
- InspectionWorker.cs
- Icon.cs
- EncoderParameter.cs
- ScrollChangedEventArgs.cs
- DataIdProcessor.cs
- LicenseManager.cs
- CheckBoxFlatAdapter.cs