Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / ResourceReferenceExpression.cs / 1586769 / 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;
// RemoveChangedHandler will have already been called via InvalidateMentorCache().
_weakContainerRRE = 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.RemoveInflatedListener(this);
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)
{
// VS has a scenario where a TreeWalk invalidates all reference expressions on a DependencyObject.
// If there is a dependency between RRE's,
// invalidating one RRE could cause _targetObject to be null on the other RRE. Hence this check.
if (_targetObject == null)
{
return;
}
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 )
{
if (_weakContainerRRE == null)
{
_weakContainerRRE = new ResourceReferenceExpressionWeakContainer(this);
}
// Hook up the event to the weak container to prevent memory leaks (Bug436021)
_weakContainerRRE.AddChangedHandler(resourceAsFreezable);
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 && _weakContainerRRE != null)
{
if (!resourceAsFreezable.IsFrozen)
{
_weakContainerRRE.RemoveChangedHandler();
}
else
{
// Resource is frozen so we can discard the weak reference.
_weakContainerRRE = null;
}
}
// 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
internal void OnDeferredResourceInflated(DeferredResourceReference deferredResourceReference)
{
if (ReadInternalState(InternalState.IsListeningForInflated))
{
// once the value is inflated, stop listening for the event
deferredResourceReference.RemoveInflatedListener(this);
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)
private ResourceReferenceExpressionWeakContainer _weakContainerRRE = null;
///
/// 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,
}
#region ResourceReferenceExpressionWeakContainer
///
/// ResourceReferenceExpressionWeakContainer handles the Freezable.Changed event
/// without holding a strong reference to ResourceReferenceExpression.
///
private class ResourceReferenceExpressionWeakContainer : WeakReference
{
public ResourceReferenceExpressionWeakContainer(ResourceReferenceExpression target)
: base(target) {}
private void InvalidateTargetSubProperty(object sender, EventArgs args)
{
ResourceReferenceExpression expression = (ResourceReferenceExpression)Target;
if (expression != null)
{
expression.InvalidateTargetSubProperty(sender, args);
}
else
{
RemoveChangedHandler();
}
}
public void AddChangedHandler(Freezable resource)
{
// If _resource already exists, unhook the event handler.
if (_resource != null)
{
RemoveChangedHandler();
}
_resource = resource;
Debug.Assert(!_resource.IsFrozen);
_resource.Changed += new EventHandler(this.InvalidateTargetSubProperty);
}
public void RemoveChangedHandler()
{
Debug.Assert(!_resource.IsFrozen);
_resource.Changed -= new EventHandler(this.InvalidateTargetSubProperty);
_resource = null;
}
private Freezable _resource;
}
#endregion
}
///
/// 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;
// RemoveChangedHandler will have already been called via InvalidateMentorCache().
_weakContainerRRE = 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.RemoveInflatedListener(this);
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)
{
// VS has a scenario where a TreeWalk invalidates all reference expressions on a DependencyObject.
// If there is a dependency between RRE's,
// invalidating one RRE could cause _targetObject to be null on the other RRE. Hence this check.
if (_targetObject == null)
{
return;
}
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 )
{
if (_weakContainerRRE == null)
{
_weakContainerRRE = new ResourceReferenceExpressionWeakContainer(this);
}
// Hook up the event to the weak container to prevent memory leaks (Bug436021)
_weakContainerRRE.AddChangedHandler(resourceAsFreezable);
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 && _weakContainerRRE != null)
{
if (!resourceAsFreezable.IsFrozen)
{
_weakContainerRRE.RemoveChangedHandler();
}
else
{
// Resource is frozen so we can discard the weak reference.
_weakContainerRRE = null;
}
}
// 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
internal void OnDeferredResourceInflated(DeferredResourceReference deferredResourceReference)
{
if (ReadInternalState(InternalState.IsListeningForInflated))
{
// once the value is inflated, stop listening for the event
deferredResourceReference.RemoveInflatedListener(this);
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)
private ResourceReferenceExpressionWeakContainer _weakContainerRRE = null;
///
/// 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,
}
#region ResourceReferenceExpressionWeakContainer
///
/// ResourceReferenceExpressionWeakContainer handles the Freezable.Changed event
/// without holding a strong reference to ResourceReferenceExpression.
///
private class ResourceReferenceExpressionWeakContainer : WeakReference
{
public ResourceReferenceExpressionWeakContainer(ResourceReferenceExpression target)
: base(target) {}
private void InvalidateTargetSubProperty(object sender, EventArgs args)
{
ResourceReferenceExpression expression = (ResourceReferenceExpression)Target;
if (expression != null)
{
expression.InvalidateTargetSubProperty(sender, args);
}
else
{
RemoveChangedHandler();
}
}
public void AddChangedHandler(Freezable resource)
{
// If _resource already exists, unhook the event handler.
if (_resource != null)
{
RemoveChangedHandler();
}
_resource = resource;
Debug.Assert(!_resource.IsFrozen);
_resource.Changed += new EventHandler(this.InvalidateTargetSubProperty);
}
public void RemoveChangedHandler()
{
Debug.Assert(!_resource.IsFrozen);
_resource.Changed -= new EventHandler(this.InvalidateTargetSubProperty);
_resource = null;
}
private Freezable _resource;
}
#endregion
}
///
/// 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
- MediaTimeline.cs
- Converter.cs
- DecoderExceptionFallback.cs
- XmlChoiceIdentifierAttribute.cs
- PropertyGridEditorPart.cs
- DbProviderFactories.cs
- RegexCapture.cs
- Polyline.cs
- MetadataHelper.cs
- COM2TypeInfoProcessor.cs
- ColumnCollection.cs
- Compiler.cs
- DBParameter.cs
- ApplicationManager.cs
- ViewStateModeByIdAttribute.cs
- _Semaphore.cs
- HierarchicalDataSourceConverter.cs
- TdsParserStateObject.cs
- SiteOfOriginPart.cs
- messageonlyhwndwrapper.cs
- SchemaUtility.cs
- WindowExtensionMethods.cs
- RC2.cs
- WebPartConnectionsConnectVerb.cs
- UniqueConstraint.cs
- EdmFunctionAttribute.cs
- EmptyEnumerator.cs
- BufferedReadStream.cs
- UxThemeWrapper.cs
- HierarchicalDataSourceControl.cs
- Compiler.cs
- Privilege.cs
- ServiceMemoryGates.cs
- MiniAssembly.cs
- ListViewVirtualItemsSelectionRangeChangedEvent.cs
- ValueTypeIndexerReference.cs
- Line.cs
- MergeFilterQuery.cs
- InfoCardSymmetricAlgorithm.cs
- WindowsGraphics2.cs
- TreeNode.cs
- Help.cs
- IpcClientChannel.cs
- DataGridViewCellLinkedList.cs
- TableLayoutPanelCellPosition.cs
- HwndProxyElementProvider.cs
- CheckBoxRenderer.cs
- WebPartTracker.cs
- _LazyAsyncResult.cs
- CornerRadius.cs
- VirtualizingPanel.cs
- SecurityHelper.cs
- PropertyIdentifier.cs
- InputBuffer.cs
- Rijndael.cs
- ReferencedAssembly.cs
- MetabaseServerConfig.cs
- StringConverter.cs
- ScriptManagerProxy.cs
- SHA384.cs
- BindingCompleteEventArgs.cs
- HuffCodec.cs
- DataRelation.cs
- DashStyles.cs
- HttpListenerRequest.cs
- CollectionBase.cs
- IdentifierCollection.cs
- ObjectContextServiceProvider.cs
- TemplateLookupAction.cs
- SrgsNameValueTag.cs
- DataGridViewRowsRemovedEventArgs.cs
- PreviewKeyDownEventArgs.cs
- dbdatarecord.cs
- CustomAttribute.cs
- InvalidOleVariantTypeException.cs
- SqlXml.cs
- DomainUpDown.cs
- ClientSideQueueItem.cs
- ThreadSafeMessageFilterTable.cs
- SqlTopReducer.cs
- StringSource.cs
- XmlSchemaParticle.cs
- SolidColorBrush.cs
- Clipboard.cs
- ToolboxItemCollection.cs
- RIPEMD160.cs
- FeatureSupport.cs
- ConstantExpression.cs
- ExpressionValueEditor.cs
- CapabilitiesPattern.cs
- ObjectTypeMapping.cs
- _ChunkParse.cs
- SerializerDescriptor.cs
- EnterpriseServicesHelper.cs
- CompositeControl.cs
- ExplicitDiscriminatorMap.cs
- PasswordRecoveryAutoFormat.cs
- EventData.cs
- TextElementCollectionHelper.cs
- GridView.cs