diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs
index 390918a439c..00c3e73fcf4 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs
@@ -1735,23 +1735,31 @@ private object FetchResource(
DeferredResourceReference deferredResourceReference;
if (!IsThemeDictionary)
{
- if (_ownerApps != null)
- {
- deferredResourceReference = new DeferredAppResourceReference(this, resourceKey);
- }
- else
- {
- deferredResourceReference = new DeferredResourceReference(this, resourceKey);
- }
-
// Cache the deferredResourceReference so that it can be validated
// in case of a dictionary change prior to its inflation
if (_deferredResourceReferences == null)
{
- _deferredResourceReferences = new WeakReferenceList();
+ _deferredResourceReferences = new DeferredResourceReferenceList();
+ }
+
+ if (_deferredResourceReferences.Get(resourceKey) is { } existingDeferredResourceReference
+ && existingDeferredResourceReference.Dictionary == this)
+ {
+ deferredResourceReference = existingDeferredResourceReference;
}
+ else
+ {
+ if (_ownerApps != null)
+ {
+ deferredResourceReference = new DeferredAppResourceReference(this, resourceKey);
+ }
+ else
+ {
+ deferredResourceReference = new DeferredResourceReference(this, resourceKey);
+ }
- _deferredResourceReferences.Add( deferredResourceReference, true /*SkipFind*/);
+ _deferredResourceReferences.AddOrSet(deferredResourceReference);
+ }
}
else
{
@@ -1775,22 +1783,18 @@ private void ValidateDeferredResourceReferences(object resourceKey)
{
if (_deferredResourceReferences != null)
{
- foreach (Object o in _deferredResourceReferences)
- {
+ DeferredResourceReference deferredResourceReference = _deferredResourceReferences.Get(resourceKey);
- DeferredResourceReference deferredResourceReference = o as DeferredResourceReference;
- if (deferredResourceReference != null && (resourceKey == null || Object.Equals(resourceKey, deferredResourceReference.Key)))
- {
- // This will inflate the deferred reference, causing it
- // to be removed from the list. The list may also be
- // purged of dead references.
- deferredResourceReference.GetValue(BaseValueSourceInternal.Unknown);
- }
+ if (deferredResourceReference is not null)
+ {
+ // This will inflate the deferred reference, causing it
+ // to be removed from the list. The list may also be
+ // purged of dead references.
+ deferredResourceReference.GetValue(BaseValueSourceInternal.Unknown);
}
}
}
-
///
/// Called when the MergedDictionaries collection changes
///
@@ -2053,7 +2057,7 @@ internal WeakReferenceList ApplicationOwners
#region Properties
- internal WeakReferenceList DeferredResourceReferences
+ internal DeferredResourceReferenceList DeferredResourceReferences
{
get { return _deferredResourceReferences; }
}
@@ -2478,10 +2482,7 @@ private void MoveDeferredResourceReferencesFrom(ResourceDictionary loadedRD)
// redirect each entry toward its new owner
if (_deferredResourceReferences != null)
{
- foreach (DeferredResourceReference drr in _deferredResourceReferences)
- {
- drr.Dictionary = this;
- }
+ _deferredResourceReferences.ChangeDictionary(this);
}
}
@@ -2548,7 +2549,7 @@ private enum FallbackState
private WeakReferenceList _ownerFEs = null;
private WeakReferenceList _ownerFCEs = null;
private WeakReferenceList _ownerApps = null;
- private WeakReferenceList _deferredResourceReferences = null;
+ private DeferredResourceReferenceList _deferredResourceReferences = null;
private ObservableCollection _mergedDictionaries = null;
private Uri _source = null;
private Uri _baseUri = null;
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs
index 6246ee697f6..4a6622b9d01 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs
@@ -1739,8 +1739,9 @@ internal override object GetValue(BaseValueSourceInternal valueSource)
{
// Note that we are replacing the _keyorValue field
// with the value and deleting the _dictionary field.
- _keyOrValue = value;
RemoveFromDictionary();
+ // Update after removal from dictionary as we need the key for proper removal
+ _keyOrValue = value;
}
// Freeze if this value originated from a style or template
@@ -2032,9 +2033,103 @@ internal override bool IsUnset
#endregion Properties
}
-}
+ internal class DeferredResourceReferenceList
+ {
+ private readonly object _syncRoot = new();
+ private readonly Dictionary