Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / ResourceReferenceExpression.cs / 1 / ResourceReferenceExpression.cs
//---------------------------------------------------------------------------- // // File: ResourceReferenceExpression.cs // // Description: // Expression to evaluate a ResourceReference. // // Copyright (C) 2003 by Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Diagnostics; using System.Windows.Markup; using MS.Internal; namespace System.Windows { ////// Expression to evaluate a ResourceReference /// [TypeConverter(typeof(ResourceReferenceExpressionConverter))] internal class ResourceReferenceExpression : Expression { ////// Constructor for ResourceReferenceExpression /// /// /// Name of the resource being referenced /// public ResourceReferenceExpression(object resourceKey) { _resourceKey = resourceKey; } ////// List of sources of the ResourceReferenceExpression /// ///Sources list internal override DependencySource[] GetSources() { return null; } ////// Called to evaluate the ResourceReferenceExpression value /// /// DependencyObject being queried /// Property being queried ///Computed value. Unset if unavailable. internal override object GetValue(DependencyObject d, DependencyProperty dp) { if (d == null) { throw new ArgumentNullException("d"); } if (dp == null) { throw new ArgumentNullException("dp"); } // If the cached value is valid then return it if (ReadInternalState(InternalState.HasCachedResourceValue) == true) return _cachedResourceValue; object source; return GetRawValue(d, out source, dp); } // Clone a copy of this expression (this is used by Freezable.Copy) internal override Expression Copy( DependencyObject targetObject, DependencyProperty targetDP ) { return new ResourceReferenceExpression( ResourceKey ); } ////// Called to evaluate the ResourceReferenceExpression value /// /// DependencyObject being queried /// Source object that the resource is found on /// DependencyProperty ///Computed value. Unset if unavailable. ////// This routine has been separated from the above GetValue call because it is /// invoked by the ResourceReferenceExpressionConverter during serialization. /// internal object GetRawValue(DependencyObject d, out object source, DependencyProperty dp) { // Find the mentor node to invoke FindResource on. For example // /// Allows ResourceReferenceExpression to store set values /// /// DependencyObject being set /// Property being set /// Value being set ///true if ResourceReferenceExpression handled storing of the value internal override bool SetValue(DependencyObject d, DependencyProperty dp, object value) { return false; } ////// Notification that the ResourceReferenceExpression has been set as a property's value /// /// DependencyObject being set /// Property being set internal override void OnAttach(DependencyObject d, DependencyProperty dp) { _targetObject = d; _targetProperty = dp; FrameworkObject fo = new FrameworkObject(_targetObject); fo.HasResourceReference = true; if (!fo.IsValid) { // Listen for the InheritanceContextChanged event on the target node, // so that if this context hierarchy changes we can re-evaluate this expression. _targetObject.InheritanceContextChanged += new EventHandler(InvalidateExpressionValue); } } ////// Notification that the ResourceReferenceExpression has been removed as a property's value /// /// DependencyObject being cleared /// Property being cleared internal override void OnDetach(DependencyObject d, DependencyProperty dp) { // Invalidate all the caches InvalidateMentorCache(); if (!(_targetObject is FrameworkElement) && !(_targetObject is FrameworkContentElement)) { // Stop listening for the InheritanceContextChanged event on the target node _targetObject.InheritanceContextChanged -= new EventHandler(InvalidateExpressionValue); } _targetObject = null; _targetProperty = null; } ////// Key used to lookup the resource /// public object ResourceKey { get { return _resourceKey; } } ////// This method is called when the cached value of the resource has /// been invalidated. E.g. after a new Resources property is set somewhere /// in the ancestory. /// private void InvalidateCacheValue() { object resource = _cachedResourceValue; // If the old value was a DeferredResourceReference, it should be // removed from its Dictionary's list to avoid a leak (bug 1624666). DeferredResourceReference deferredResourceReference = _cachedResourceValue as DeferredResourceReference; if (deferredResourceReference != null) { if (deferredResourceReference.IsInflated) { // use the inflated value for the Freezable test below resource = deferredResourceReference.Value; } else { // stop listening for the Inflated event if (ReadInternalState(InternalState.IsListeningForInflated)) { deferredResourceReference.Inflated -= new EventHandler(OnDeferredResourceInflated); WriteInternalState(InternalState.IsListeningForInflated, false); } } deferredResourceReference.RemoveFromDictionary(); } StopListeningForFreezableChanges(resource); _cachedResourceValue = null; WriteInternalState(InternalState.HasCachedResourceValue, false); } ////// This method is called to invalidate all the cached values held in /// this expression. This is called under the following 3 scenarios /// 1. InheritanceContext changes /// 2. Logical tree changes /// 3. ResourceDictionary changes /// This call is more pervasive than the InvalidateCacheValue method /// private void InvalidateMentorCache() { if (ReadInternalState(InternalState.IsMentorCacheValid) == true) { if (_mentorCache != null) { if (_mentorCache != _targetObject) { FrameworkElement mentorFE; FrameworkContentElement mentorFCE; Helper.DowncastToFEorFCE(_mentorCache, out mentorFE, out mentorFCE, true); // Your mentor is about to change, make sure you detach handlers for // the events that you were listening on the old mentor if (mentorFE != null) { mentorFE.ResourcesChanged -= new EventHandler(InvalidateExpressionValue); } else { mentorFCE.ResourcesChanged -= new EventHandler(InvalidateExpressionValue); } } // Drop the mentor cache _mentorCache = null; } // Mark the cache invalid WriteInternalState(InternalState.IsMentorCacheValid, false); } // Invalidate the cached value of the expression InvalidateCacheValue(); } ////// This event handler is called to invalidate the cached value held in /// this expression. This is called under the following 3 scenarios /// 1. InheritanceContext changes /// 2. Logical tree changes /// 3. ResourceDictionary changes /// internal void InvalidateExpressionValue(object sender, EventArgs e) { ResourcesChangedEventArgs args = e as ResourcesChangedEventArgs; if (args != null) { ResourcesChangeInfo info = args.Info; if (!info.IsTreeChange) { // This will happen when // 1. Theme changes // 2. Entire ResourceDictionary in the ancestry changes // 3. Single entry in a ResourceDictionary in the ancestry is changed // In all of the above cases it is sufficient to re-evaluate the cache // value alone. The mentor relation ships stay the same. InvalidateCacheValue(); } else { // This is the case of a logical tree change and hence we need to // re-evaluate both the mentor and the cached value. InvalidateMentorCache(); } } else { // There is no information provided by the EventArgs. Hence we // pessimistically invalidate both the mentor and the cached value. // This code path will execute when the InheritanceContext changes. InvalidateMentorCache(); } InvalidateTargetProperty(sender, e); } private void InvalidateTargetProperty(object sender, EventArgs e) { _targetObject.InvalidateProperty(_targetProperty); } private void InvalidateTargetSubProperty(object sender, EventArgs e) { _targetObject.NotifySubPropertyChange(_targetProperty); } private void ListenForFreezableChanges(object resource) { if (!ReadInternalState(InternalState.IsListeningForFreezableChanges)) { // If this value is an unfrozen Freezable object, we need // to listen to its changed event in order to properly update // the cache. Freezable resourceAsFreezable = resource as Freezable; if( resourceAsFreezable != null && !resourceAsFreezable.IsFrozen ) { resourceAsFreezable.Changed += new EventHandler(InvalidateTargetSubProperty); WriteInternalState(InternalState.IsListeningForFreezableChanges, true); } } } private void StopListeningForFreezableChanges(object resource) { if (ReadInternalState(InternalState.IsListeningForFreezableChanges)) { // If the old value was an unfrozen Freezable object, we need // to stop listening to its changed event. If the old value wasn't // frozen (hence we attached an listener) but has been frozen // since then, the change handler we had attached was already // discarded during the freeze so we don't care here. Freezable resourceAsFreezable = resource as Freezable; if( resourceAsFreezable != null && !resourceAsFreezable.IsFrozen ) { resourceAsFreezable.Changed -= new EventHandler(InvalidateTargetSubProperty); } // It is possible that a freezable was unfrozen during the call to ListForFreezableChanges // but was frozen before the call to StopListeningForFreezableChanges WriteInternalState(InternalState.IsListeningForFreezableChanges, false); } } // when a deferred resource reference is inflated, the value may need extra // work private void OnDeferredResourceInflated(object sender, EventArgs e) { DeferredResourceReference deferredResourceReference = (DeferredResourceReference)sender; // once the value is inflated, stop listening for the event deferredResourceReference.Inflated -= new EventHandler(OnDeferredResourceInflated); WriteInternalState(InternalState.IsListeningForInflated, false); ListenForFreezableChanges(deferredResourceReference.Value); } // Extracts the required flag and returns // bool to indicate if it is set or unset private bool ReadInternalState(InternalState reqFlag) { return (_state & reqFlag) != 0; } // Sets or Unsets the required flag based on // the bool argument private void WriteInternalState(InternalState reqFlag, bool set) { if (set) { _state |= reqFlag; } else { _state &= (~reqFlag); } } private object _resourceKey; // Name of the resource being referenced by this expression // Cached value and a dirty bit. See GetValue. private object _cachedResourceValue; // Used to find the value for this expression when it is set on a non-FE/FCE. // The mentor is the FE/FCE that the FindResource method is invoked on. private DependencyObject _mentorCache; // Used by the change listener to fire invalidation. private DependencyObject _targetObject; private DependencyProperty _targetProperty; // Bit Fields used to store boolean flags private InternalState _state = InternalState.Default; // this is a byte (see def'n) ////// This enum represents the internal state of the RRE. /// Additional bools should be coalesced into this enum. /// [Flags] private enum InternalState : byte { Default = 0x00, HasCachedResourceValue = 0x01, IsMentorCacheValid = 0x02, DisableThrowOnResourceFailure = 0x04, IsListeningForFreezableChanges= 0x08, IsListeningForInflated = 0x10, } } ////// These EventArgs are used to pass additional /// information during a ResourcesChanged event /// internal class ResourcesChangedEventArgs : EventArgs { internal ResourcesChangedEventArgs(ResourcesChangeInfo info) { _info = info; } internal ResourcesChangeInfo Info { get { return _info; } } private ResourcesChangeInfo _info; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // File: ResourceReferenceExpression.cs // // Description: // Expression to evaluate a ResourceReference. // // Copyright (C) 2003 by Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Diagnostics; using System.Windows.Markup; using MS.Internal; namespace System.Windows { ////// Expression to evaluate a ResourceReference /// [TypeConverter(typeof(ResourceReferenceExpressionConverter))] internal class ResourceReferenceExpression : Expression { ////// Constructor for ResourceReferenceExpression /// /// /// Name of the resource being referenced /// public ResourceReferenceExpression(object resourceKey) { _resourceKey = resourceKey; } ////// List of sources of the ResourceReferenceExpression /// ///Sources list internal override DependencySource[] GetSources() { return null; } ////// Called to evaluate the ResourceReferenceExpression value /// /// DependencyObject being queried /// Property being queried ///Computed value. Unset if unavailable. internal override object GetValue(DependencyObject d, DependencyProperty dp) { if (d == null) { throw new ArgumentNullException("d"); } if (dp == null) { throw new ArgumentNullException("dp"); } // If the cached value is valid then return it if (ReadInternalState(InternalState.HasCachedResourceValue) == true) return _cachedResourceValue; object source; return GetRawValue(d, out source, dp); } // Clone a copy of this expression (this is used by Freezable.Copy) internal override Expression Copy( DependencyObject targetObject, DependencyProperty targetDP ) { return new ResourceReferenceExpression( ResourceKey ); } ////// Called to evaluate the ResourceReferenceExpression value /// /// DependencyObject being queried /// Source object that the resource is found on /// DependencyProperty ///Computed value. Unset if unavailable. ////// This routine has been separated from the above GetValue call because it is /// invoked by the ResourceReferenceExpressionConverter during serialization. /// internal object GetRawValue(DependencyObject d, out object source, DependencyProperty dp) { // Find the mentor node to invoke FindResource on. For example // /// Allows ResourceReferenceExpression to store set values /// /// DependencyObject being set /// Property being set /// Value being set ///true if ResourceReferenceExpression handled storing of the value internal override bool SetValue(DependencyObject d, DependencyProperty dp, object value) { return false; } ////// Notification that the ResourceReferenceExpression has been set as a property's value /// /// DependencyObject being set /// Property being set internal override void OnAttach(DependencyObject d, DependencyProperty dp) { _targetObject = d; _targetProperty = dp; FrameworkObject fo = new FrameworkObject(_targetObject); fo.HasResourceReference = true; if (!fo.IsValid) { // Listen for the InheritanceContextChanged event on the target node, // so that if this context hierarchy changes we can re-evaluate this expression. _targetObject.InheritanceContextChanged += new EventHandler(InvalidateExpressionValue); } } ////// Notification that the ResourceReferenceExpression has been removed as a property's value /// /// DependencyObject being cleared /// Property being cleared internal override void OnDetach(DependencyObject d, DependencyProperty dp) { // Invalidate all the caches InvalidateMentorCache(); if (!(_targetObject is FrameworkElement) && !(_targetObject is FrameworkContentElement)) { // Stop listening for the InheritanceContextChanged event on the target node _targetObject.InheritanceContextChanged -= new EventHandler(InvalidateExpressionValue); } _targetObject = null; _targetProperty = null; } ////// Key used to lookup the resource /// public object ResourceKey { get { return _resourceKey; } } ////// This method is called when the cached value of the resource has /// been invalidated. E.g. after a new Resources property is set somewhere /// in the ancestory. /// private void InvalidateCacheValue() { object resource = _cachedResourceValue; // If the old value was a DeferredResourceReference, it should be // removed from its Dictionary's list to avoid a leak (bug 1624666). DeferredResourceReference deferredResourceReference = _cachedResourceValue as DeferredResourceReference; if (deferredResourceReference != null) { if (deferredResourceReference.IsInflated) { // use the inflated value for the Freezable test below resource = deferredResourceReference.Value; } else { // stop listening for the Inflated event if (ReadInternalState(InternalState.IsListeningForInflated)) { deferredResourceReference.Inflated -= new EventHandler(OnDeferredResourceInflated); WriteInternalState(InternalState.IsListeningForInflated, false); } } deferredResourceReference.RemoveFromDictionary(); } StopListeningForFreezableChanges(resource); _cachedResourceValue = null; WriteInternalState(InternalState.HasCachedResourceValue, false); } ////// This method is called to invalidate all the cached values held in /// this expression. This is called under the following 3 scenarios /// 1. InheritanceContext changes /// 2. Logical tree changes /// 3. ResourceDictionary changes /// This call is more pervasive than the InvalidateCacheValue method /// private void InvalidateMentorCache() { if (ReadInternalState(InternalState.IsMentorCacheValid) == true) { if (_mentorCache != null) { if (_mentorCache != _targetObject) { FrameworkElement mentorFE; FrameworkContentElement mentorFCE; Helper.DowncastToFEorFCE(_mentorCache, out mentorFE, out mentorFCE, true); // Your mentor is about to change, make sure you detach handlers for // the events that you were listening on the old mentor if (mentorFE != null) { mentorFE.ResourcesChanged -= new EventHandler(InvalidateExpressionValue); } else { mentorFCE.ResourcesChanged -= new EventHandler(InvalidateExpressionValue); } } // Drop the mentor cache _mentorCache = null; } // Mark the cache invalid WriteInternalState(InternalState.IsMentorCacheValid, false); } // Invalidate the cached value of the expression InvalidateCacheValue(); } ////// This event handler is called to invalidate the cached value held in /// this expression. This is called under the following 3 scenarios /// 1. InheritanceContext changes /// 2. Logical tree changes /// 3. ResourceDictionary changes /// internal void InvalidateExpressionValue(object sender, EventArgs e) { ResourcesChangedEventArgs args = e as ResourcesChangedEventArgs; if (args != null) { ResourcesChangeInfo info = args.Info; if (!info.IsTreeChange) { // This will happen when // 1. Theme changes // 2. Entire ResourceDictionary in the ancestry changes // 3. Single entry in a ResourceDictionary in the ancestry is changed // In all of the above cases it is sufficient to re-evaluate the cache // value alone. The mentor relation ships stay the same. InvalidateCacheValue(); } else { // This is the case of a logical tree change and hence we need to // re-evaluate both the mentor and the cached value. InvalidateMentorCache(); } } else { // There is no information provided by the EventArgs. Hence we // pessimistically invalidate both the mentor and the cached value. // This code path will execute when the InheritanceContext changes. InvalidateMentorCache(); } InvalidateTargetProperty(sender, e); } private void InvalidateTargetProperty(object sender, EventArgs e) { _targetObject.InvalidateProperty(_targetProperty); } private void InvalidateTargetSubProperty(object sender, EventArgs e) { _targetObject.NotifySubPropertyChange(_targetProperty); } private void ListenForFreezableChanges(object resource) { if (!ReadInternalState(InternalState.IsListeningForFreezableChanges)) { // If this value is an unfrozen Freezable object, we need // to listen to its changed event in order to properly update // the cache. Freezable resourceAsFreezable = resource as Freezable; if( resourceAsFreezable != null && !resourceAsFreezable.IsFrozen ) { resourceAsFreezable.Changed += new EventHandler(InvalidateTargetSubProperty); WriteInternalState(InternalState.IsListeningForFreezableChanges, true); } } } private void StopListeningForFreezableChanges(object resource) { if (ReadInternalState(InternalState.IsListeningForFreezableChanges)) { // If the old value was an unfrozen Freezable object, we need // to stop listening to its changed event. If the old value wasn't // frozen (hence we attached an listener) but has been frozen // since then, the change handler we had attached was already // discarded during the freeze so we don't care here. Freezable resourceAsFreezable = resource as Freezable; if( resourceAsFreezable != null && !resourceAsFreezable.IsFrozen ) { resourceAsFreezable.Changed -= new EventHandler(InvalidateTargetSubProperty); } // It is possible that a freezable was unfrozen during the call to ListForFreezableChanges // but was frozen before the call to StopListeningForFreezableChanges WriteInternalState(InternalState.IsListeningForFreezableChanges, false); } } // when a deferred resource reference is inflated, the value may need extra // work private void OnDeferredResourceInflated(object sender, EventArgs e) { DeferredResourceReference deferredResourceReference = (DeferredResourceReference)sender; // once the value is inflated, stop listening for the event deferredResourceReference.Inflated -= new EventHandler(OnDeferredResourceInflated); WriteInternalState(InternalState.IsListeningForInflated, false); ListenForFreezableChanges(deferredResourceReference.Value); } // Extracts the required flag and returns // bool to indicate if it is set or unset private bool ReadInternalState(InternalState reqFlag) { return (_state & reqFlag) != 0; } // Sets or Unsets the required flag based on // the bool argument private void WriteInternalState(InternalState reqFlag, bool set) { if (set) { _state |= reqFlag; } else { _state &= (~reqFlag); } } private object _resourceKey; // Name of the resource being referenced by this expression // Cached value and a dirty bit. See GetValue. private object _cachedResourceValue; // Used to find the value for this expression when it is set on a non-FE/FCE. // The mentor is the FE/FCE that the FindResource method is invoked on. private DependencyObject _mentorCache; // Used by the change listener to fire invalidation. private DependencyObject _targetObject; private DependencyProperty _targetProperty; // Bit Fields used to store boolean flags private InternalState _state = InternalState.Default; // this is a byte (see def'n) ////// This enum represents the internal state of the RRE. /// Additional bools should be coalesced into this enum. /// [Flags] private enum InternalState : byte { Default = 0x00, HasCachedResourceValue = 0x01, IsMentorCacheValid = 0x02, DisableThrowOnResourceFailure = 0x04, IsListeningForFreezableChanges= 0x08, IsListeningForInflated = 0x10, } } ////// These EventArgs are used to pass additional /// information during a ResourcesChanged event /// internal class ResourcesChangedEventArgs : EventArgs { internal ResourcesChangedEventArgs(ResourcesChangeInfo info) { _info = info; } internal ResourcesChangeInfo Info { get { return _info; } } private ResourcesChangeInfo _info; } } // 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
- XmlSiteMapProvider.cs
- XmlSchemaSearchPattern.cs
- XAMLParseException.cs
- FatalException.cs
- TableCellCollection.cs
- ObjectItemLoadingSessionData.cs
- QueryGenerator.cs
- ClientApiGenerator.cs
- ZoneMembershipCondition.cs
- TableStyle.cs
- CryptoConfig.cs
- BitmapImage.cs
- ProcessThread.cs
- ContentValidator.cs
- DynamicDataManager.cs
- SqlDeflator.cs
- AssemblySettingAttributes.cs
- SchemaNames.cs
- PackageRelationshipSelector.cs
- DataContract.cs
- brushes.cs
- RegexCapture.cs
- AnnotationAuthorChangedEventArgs.cs
- AdPostCacheSubstitution.cs
- PropertyEntry.cs
- ServerIdentity.cs
- ToolStripRendererSwitcher.cs
- Matrix3DConverter.cs
- BitmapFrame.cs
- ToolStripAdornerWindowService.cs
- EntityProviderFactory.cs
- BaseDataListActionList.cs
- RemoteWebConfigurationHostStream.cs
- FixUpCollection.cs
- IriParsingElement.cs
- FontStyleConverter.cs
- Int64Converter.cs
- ComContractElementCollection.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- AsymmetricKeyExchangeDeformatter.cs
- ByteKeyFrameCollection.cs
- DelayLoadType.cs
- DataStorage.cs
- Activity.cs
- DataSourceControl.cs
- XamlNamespaceHelper.cs
- ProcessProtocolHandler.cs
- PlainXmlDeserializer.cs
- HealthMonitoringSectionHelper.cs
- TemplateBindingExtensionConverter.cs
- HyperLink.cs
- HttpResponseHeader.cs
- XmlSerializerAssemblyAttribute.cs
- WebEventCodes.cs
- ScrollProperties.cs
- HttpContextServiceHost.cs
- WindowsFormsHostAutomationPeer.cs
- ImplicitInputBrush.cs
- PathGeometry.cs
- SiteMapNodeCollection.cs
- TreeViewImageGenerator.cs
- PlainXmlWriter.cs
- ChtmlFormAdapter.cs
- DataGridViewCellCancelEventArgs.cs
- RenderTargetBitmap.cs
- AlgoModule.cs
- Schedule.cs
- KnownBoxes.cs
- PeerNearMe.cs
- StringComparer.cs
- WebBrowserProgressChangedEventHandler.cs
- CardSpaceException.cs
- XmlStreamStore.cs
- ServiceRoute.cs
- TreeNodeEventArgs.cs
- TrustVersion.cs
- ZoneLinkButton.cs
- AssociationTypeEmitter.cs
- ControlType.cs
- DefaultShape.cs
- XsdBuildProvider.cs
- WorkflowInstanceProxy.cs
- XhtmlConformanceSection.cs
- RadioButtonStandardAdapter.cs
- DrawListViewSubItemEventArgs.cs
- FileUtil.cs
- TransformPatternIdentifiers.cs
- XmlDataSourceView.cs
- TreeNodeStyleCollectionEditor.cs
- Debug.cs
- MatrixStack.cs
- GroupItemAutomationPeer.cs
- EditBehavior.cs
- Int32AnimationBase.cs
- SecurityDocument.cs
- WinOEToolBoxItem.cs
- FatalException.cs
- SafeRightsManagementHandle.cs
- ExceptionUtil.cs
- ToolStripStatusLabel.cs