Skip to content

Clear IsThemeDictionary flag when ResourceDictionary gains an owner#11727

Open
amarinov-msft wants to merge 2 commits into
dotnet:mainfrom
amarinov-msft:amarinov-fix/app-resources-marked-as-theme-dictionary
Open

Clear IsThemeDictionary flag when ResourceDictionary gains an owner#11727
amarinov-msft wants to merge 2 commits into
dotnet:mainfrom
amarinov-msft:amarinov-fix/app-resources-marked-as-theme-dictionary

Conversation

@amarinov-msft

@amarinov-msft amarinov-msft commented Jun 17, 2026

Copy link
Copy Markdown

Fixes #11714

Description

Application.Resources (and Window/FrameworkElement.Resources) could be incorrectly marked as a theme dictionary, after which any dictionary merged into it inherited the same flag. This led to wrong resources being cached in SystemResources and, in some cases, a NullReferenceException in StyleHelper.GetInstanceValue() when a misclassified style was applied to a container.

Root cause: the ResourceDictionary constructor inherits IsThemeDictionary from the ambient SystemResources.IsSystemResourcesParsing flag. The Resources property getters lazily construct their dictionary on first access, so if that first access happens while system resources are being parsed, the dictionary is permanently flagged as a theme dictionary.

Fix: in ResourceDictionary.AddOwner, clear IsThemeDictionary when the owner is an Application, FrameworkElement, or FrameworkContentElement. The getters call AddOwner immediately after construction, so the flag is corrected before it can be observed or propagated. The IsThemeDictionary setter already propagates the cleared value to merged dictionaries.

Customer Impact

Applications can crash with a NullReferenceException during normal UI operations (e.g. adding items to an ItemsControl) whenever the application/window resource dictionary happens to be created while system resources are being parsed. The failure is timing-dependent and hard to diagnose, and there is no reliable workaround.

Regression

Yes, it is regressed in .NET 9. The constructor heuristic and the lazy getters are unchanged from previous releases, but the .NET 9 Fluent theming feature (ThemeMode / ThemeManager) introduced new reads of the public Application.Current.Resources / Window.Resources getters from within resource-change/theme-sync handling. These getters can now run while system resources are parsing and lazily create the dictionary at the wrong moment, exposing the latent misclassification. It does not reproduce on .NET 8.

Testing

Tested against the issue's minimal repro. The debug assertion that Application.Resources had become a theme dictionary no longer fires, and the button click no longer throws.

Risk

Low. The change is a single, narrowly scoped assignment at the point an Application / FrameworkElement / FrameworkContentElement becomes an owner. For the common case the flag is already false, so the setter's change-guard makes it a no-op with negligible overhead. Genuine theme/generic dictionaries are unaffected because they never receive these owner types. The setter's existing propagation to merged dictionaries keeps state consistent.

Microsoft Reviewers: Open in CodeFlow

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@amarinov-msft amarinov-msft requested review from a team and Copilot June 17, 2026 18:14
@amarinov-msft amarinov-msft added the PR metadata: Label to tag PRs, to facilitate with triage label Jun 17, 2026
@amarinov-msft amarinov-msft requested a review from a team as a code owner June 17, 2026 18:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression where Application.Resources / Window.Resources / element Resources dictionaries could be incorrectly flagged as theme dictionaries when first constructed during system resource parsing, leading to incorrect SystemResources caching and potential NullReferenceException during style application.

Changes:

  • Clear the IsThemeDictionary flag in ResourceDictionary.AddOwner when the owner is an Application, FrameworkElement, or FrameworkContentElement.
  • Rely on the existing IsThemeDictionary setter propagation to ensure merged dictionaries get the corrected (cleared) state.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ry.AddOwner

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR metadata: Label to tag PRs, to facilitate with triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Application resource dictionary can become a theme dictionary and cause crashes

2 participants