Skip to content

Fix implicit styles with BasedOn chains breaking in 10.0.20#33218

Closed
StephaneDelcroix wants to merge 3 commits intomainfrom
fix/issue-33203-implicit-styles-regression
Closed

Fix implicit styles with BasedOn chains breaking in 10.0.20#33218
StephaneDelcroix wants to merge 3 commits intomainfrom
fix/issue-33203-implicit-styles-regression

Conversation

@StephaneDelcroix
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

This fixes issue #33203 where implicit styles using BasedOn with keyed styles stopped working in 10.0.20.

Root Cause

The regression was introduced by PR #32711 which fixed #9648 (ApplyToDerivedTypes not working for implicit styles). That fix created wrapper styles to merge multiple applicable implicit styles, but in doing so it replaced the original BasedOn chain with a new one, losing the connection to keyed styles that defined the actual property values.

The Fix

Instead of creating wrapper styles that break BasedOn chains, we now store the list of applicable implicit styles and apply them sequentially during Apply(). This preserves each style's BasedOn chain intact while still supporting the ApplyToDerivedTypes functionality from #9648.

Test Results

  • ✅ All 6 tests for ApplyToDerivedTypes not working for implicit styles #9648 (ApplyToDerivedTypes fix) still pass
  • ✅ All 1776 XAML unit tests pass (8 skipped, 0 failed)
  • ✅ All 164 Style-related Controls.Core unit tests pass
  • ✅ User's reproduction scenario (keyed style with BasedOn) now works correctly

Issues Fixed

Fixes #33203

Copilot AI review requested due to automatic review settings December 18, 2025 16:08
@StephaneDelcroix StephaneDelcroix added this to the .NET 10.0 SR3 milestone Dec 18, 2025
@StephaneDelcroix StephaneDelcroix added t/bug Something isn't working area-xaml XAML, CSS, Triggers, Behaviors i/regression This issue described a confirmed regression on a currently supported version labels Dec 18, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a regression in .NET MAUI 10.0.20 where implicit styles using BasedOn chains with keyed styles stopped working. The issue was introduced by PR #32711 which fixed ApplyToDerivedTypes functionality.

Key Changes

  • Changed merging strategy: Instead of creating wrapper styles that broke BasedOn chains, the fix now stores multiple applicable implicit styles in a list and applies them sequentially
  • Preserved BasedOn chains: Each style's BasedOn chain remains intact, ensuring property values from keyed styles are properly resolved
  • Maintained ApplyToDerivedTypes support: The fix continues to support multiple implicit styles from the type hierarchy while fixing the regression

Comment on lines +111 to +127
// Apply implicit styles from most base to most derived
// This ensures derived styles override base styles for conflicting properties
if (_applicableImplicitStyles != null && _applicableImplicitStyles.Count > 0)
{
// Apply in reverse order (most base first, most derived last)
// so derived styles override base styles
for (int i = _applicableImplicitStyles.Count - 1; i >= 0; i--)
{
//NOTE specificity could be more fine grained (using distance)
((IStyle)_applicableImplicitStyles[i]).Apply(bindable, new SetterSpecificity(SetterSpecificity.StyleImplicit, 0, 0, 0));
}
}
else
{
//NOTE specificity could be more fine grained (using distance)
ImplicitStyle?.Apply(bindable, new SetterSpecificity(SetterSpecificity.StyleImplicit, 0, 0, 0));
}
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

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

The logic for applying and unapplying multiple implicit styles is duplicated across multiple methods (Apply() at lines 113-127, UnApply() at lines 145-155, and SetStyle() at lines 254-264 and 275-286). Consider extracting this logic into private helper methods like ApplyImplicitStyles(BindableObject target) and UnApplyImplicitStyles(BindableObject target) to eliminate duplication and ensure consistency. This would improve maintainability and reduce the risk of introducing bugs when updating the style application logic in the future.

Copilot uses AI. Check for mistakes.
Comment on lines +202 to +204
// Set ImplicitStyle to the most derived style for compatibility
// (some code may check if ImplicitStyle is set)
ImplicitStyle = applicableStyles[0];
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

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

Setting ImplicitStyle to the most derived style (applicableStyles[0]) when multiple applicable styles exist may lead to unexpected behavior or confusion. Code that checks if ImplicitStyle is set may not realize there are multiple styles being applied. Consider either:

  1. Setting ImplicitStyle to null when multiple styles are present to make it clear that the _applicableImplicitStyles list should be used instead
  2. Adding a property or method to indicate when multiple implicit styles are active
    This would make the multi-style state more explicit and prevent potential misuse of the ImplicitStyle property.
Suggested change
// Set ImplicitStyle to the most derived style for compatibility
// (some code may check if ImplicitStyle is set)
ImplicitStyle = applicableStyles[0];
// When multiple implicit styles are active, leave ImplicitStyle null
// so callers know to consult _applicableImplicitStyles instead.
ImplicitStyle = null;

Copilot uses AI. Check for mistakes.
jfversluis
jfversluis previously approved these changes Dec 19, 2025
@PureWeen
Copy link
Copy Markdown
Member

/rebase

@github-actions github-actions Bot force-pushed the fix/issue-33203-implicit-styles-regression branch from cfba365 to 6ac9db6 Compare December 29, 2025 21:39
@PureWeen
Copy link
Copy Markdown
Member

/rebase

@github-project-automation github-project-automation Bot moved this from Todo to Approved in MAUI SDK Ongoing Dec 30, 2025
This fixes issue #33203 where implicit styles using BasedOn with keyed styles
stopped working in 10.0.20. The regression was introduced by PR #32711 which
fixed #9648 (ApplyToDerivedTypes not working for implicit styles).

The problem was that when merging multiple applicable implicit styles, the
code created wrapper styles that replaced the original BasedOn chain, losing
the connection to keyed styles that defined the actual property values.

The fix changes the approach: instead of creating wrapper styles that break
BasedOn chains, we now store the list of applicable implicit styles and apply
them sequentially during Apply(). This preserves each style's BasedOn chain
intact while still supporting the ApplyToDerivedTypes functionality from #9648.

Fixes #33203
Tests verify that:
1. Implicit styles with BasedOn to keyed styles work correctly
2. Derived implicit styles properly override base styles' properties
When a base style uses AppThemeBinding for a property and a derived style
overrides that property with a static value, the AppThemeBinding would
re-apply when theme changes or resources propagate, overwriting the
derived style's value.

Changes:
- AppThemeBinding.Apply(fromTarget): Skip re-apply when value is set from target
- AppThemeBinding.ApplyCore(): Check if current value was set by this binding
  before re-applying (using IsValueFromThisBinding helper)
- MergedStyle: Apply graduated specificities for multiple implicit styles

Added unit test Maui33203AppTheme to verify derived style setters override
base style's AppThemeBinding in both Light and Dark modes.
@github-actions github-actions Bot force-pushed the fix/issue-33203-implicit-styles-regression branch from 6ac9db6 to 46d0b16 Compare December 30, 2025 15:49
Copy link
Copy Markdown
Member

@PureWeen PureWeen left a comment

Choose a reason for hiding this comment

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

I'm pretty sure the failures on this one are legit UI test failures.

@github-project-automation github-project-automation Bot moved this from Approved to Changes Requested in MAUI SDK Ongoing Dec 30, 2025
@PureWeen PureWeen closed this Jan 6, 2026
@github-project-automation github-project-automation Bot moved this from Changes Requested to Done in MAUI SDK Ongoing Jan 6, 2026
Copilot AI added a commit that referenced this pull request Jan 6, 2026
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
github-actions Bot pushed a commit that referenced this pull request Jan 7, 2026
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
PureWeen added a commit that referenced this pull request Jan 8, 2026
…" (#33397)

- [x] Revert `MergedStyle.cs` to original state (restore simple
`OnImplicitStyleChanged()` method)
- [x] Delete test file `Maui9648.xaml`
- [x] Delete test file `Maui9648.xaml.cs`
- [x] Delete benchmark file `ImplicitStylesBenchmark.cs`
- [x] Add passing tests from PR #33218 for issue #33203
- [x] Remove failing AppTheme tests

### Description of Change

Reverts the changes from #32711 which modified how implicit styles with
`ApplyToDerivedTypes=true` are applied.

The original behavior returns early with the first applicable implicit
style instead of merging multiple styles from the type hierarchy.

### Issues Fixed

Fixes #33203

### Test Results

**Maui33203 Tests (6/6 PASS):**
- `ImplicitStyleWithBasedOnKeyedStyleWorks` - All 3 inflators PASSED ✅
- `DerivedImplicitStyleOverridesBaseStyle` - All 3 inflators PASSED ✅

<!-- START COPILOT CODING AGENT SUFFIX -->



<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> Revert this PR #32711


</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/dotnet/maui/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators Feb 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-xaml XAML, CSS, Triggers, Behaviors i/regression This issue described a confirmed regression on a currently supported version t/bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

10.0.20 breaks implicit styles ApplyToDerivedTypes not working for implicit styles

4 participants