Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Base / System / Windows / PropertyMetadata.cs / 1 / 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; } } ////// 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; } } 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; // [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
- CodeBinaryOperatorExpression.cs
- Stackframe.cs
- DirectoryRootQuery.cs
- ProtocolsConfiguration.cs
- SafePEFileHandle.cs
- MethodCallConverter.cs
- HtmlTableCell.cs
- ContractAdapter.cs
- CodeLinePragma.cs
- ValueExpressions.cs
- QilIterator.cs
- TypeGeneratedEventArgs.cs
- OleServicesContext.cs
- AttributeProviderAttribute.cs
- PassportIdentity.cs
- PropertyDescriptorGridEntry.cs
- DbConnectionFactory.cs
- RequestCache.cs
- ConfigurationException.cs
- ColorTranslator.cs
- UInt32Converter.cs
- XmlAnyElementAttribute.cs
- StringToken.cs
- SoapProtocolReflector.cs
- SerializationSectionGroup.cs
- loginstatus.cs
- SimpleFieldTemplateUserControl.cs
- SafeUserTokenHandle.cs
- ScrollBarAutomationPeer.cs
- InvalidProgramException.cs
- GenerateHelper.cs
- FutureFactory.cs
- TreeViewTemplateSelector.cs
- DocumentViewerHelper.cs
- FixedPage.cs
- CompilerCollection.cs
- AuthenticatedStream.cs
- DataSourceExpressionCollection.cs
- RadialGradientBrush.cs
- MissingMemberException.cs
- ComponentResourceKeyConverter.cs
- SafeEventLogWriteHandle.cs
- MulticastIPAddressInformationCollection.cs
- CompiledELinqQueryState.cs
- FileInfo.cs
- _HeaderInfoTable.cs
- JournalEntry.cs
- TabControlAutomationPeer.cs
- HtmlTableRowCollection.cs
- NullPackagingPolicy.cs
- Stroke.cs
- ParamArrayAttribute.cs
- SqlInternalConnection.cs
- ScopeCompiler.cs
- DurableInstanceProvider.cs
- FlowchartSizeFeature.cs
- SvcMapFile.cs
- UiaCoreApi.cs
- SqlDeflator.cs
- HtmlTextViewAdapter.cs
- Privilege.cs
- ExitEventArgs.cs
- DbDataSourceEnumerator.cs
- CopyNodeSetAction.cs
- Int32RectConverter.cs
- CodeTypeConstructor.cs
- RegexCaptureCollection.cs
- WebPartDeleteVerb.cs
- HTMLTagNameToTypeMapper.cs
- ServiceDescription.cs
- GuidConverter.cs
- HttpResponseHeader.cs
- SqlProviderManifest.cs
- SByteConverter.cs
- MetadataArtifactLoaderXmlReaderWrapper.cs
- OleTxTransactionInfo.cs
- NodeLabelEditEvent.cs
- XmlSchemaComplexContentRestriction.cs
- EdmFunction.cs
- Validator.cs
- ContentElementAutomationPeer.cs
- DesigntimeLicenseContext.cs
- NativeWindow.cs
- HttpServerVarsCollection.cs
- WmpBitmapDecoder.cs
- HttpHostedTransportConfiguration.cs
- RectAnimation.cs
- X509SecurityToken.cs
- ReferenceConverter.cs
- TemplateInstanceAttribute.cs
- ColumnWidthChangingEvent.cs
- SplineKeyFrames.cs
- SRGSCompiler.cs
- ArrangedElementCollection.cs
- ObjectStateManager.cs
- Vertex.cs
- AttachedPropertyBrowsableAttribute.cs
- SqlCrossApplyToCrossJoin.cs
- TrustSection.cs
- M3DUtil.cs