Fix issue 14778: Controls inside GroupBox no longer reflect inherited ForeColor/BackColor updates in VisualStylesMode.Net11 - #14929
Conversation
… ForeColor/BackColor updates in VisualStylesMode.Net11
There was a problem hiding this comment.
Pull request overview
Fixes WinForms Net11 modern-visual-styles rendering so button-family controls inside containers (e.g., GroupBox) correctly respect inherited ForeColor changes while not treating inherited BackColor as an explicit customization.
Changes:
- Updates Net11 ForeColor decision logic to preserve inherited non-default foreground colors.
- Updates Net11 BackColor “customization” detection to rely on explicit setting semantics (ShouldSerializeBackColor).
- Adds/updates regression tests to cover inherited ForeColor/BackColor behavior in Net11.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/System.Windows.Forms/System/Windows/Forms/Rendering/Button/AnimatedPopupButtonRenderer.cs | Adjusts automatic ForeColor selection and Net11 custom BackColor detection for popup rendering. |
| src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs | Aligns Net11 text/background color selection to preserve inherited colors and avoid inherited BackColor being treated as custom. |
| src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/CheckBoxModernAdapter.cs | Updates Net11 checkbox modern adapter ForeColor selection to preserve inherited ForeColor behavior. |
| src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/RadioButtonModernAdapter.cs | Updates Net11 radio button modern adapter ForeColor selection to preserve inherited ForeColor behavior. |
| src/test/unit/System.Windows.Forms/System/Windows/Forms/ButtonVisualStylesTests.cs | Adds/updates Net11 regression coverage for inherited BackColor and ForeColor behaviors. |
| src/test/unit/System.Windows.Forms/System/Windows/Forms/PopupButtonVisualStylesTests.cs | Adds Net11 regression coverage for inherited BackColor state-color selection in popup renderer. |
Suppressed comments (3)
src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/CheckBoxModernAdapter.cs:119
- This switches from ShouldSerializeForeColor() to (ForeColor != Control.DefaultForeColor) for choosing the preferred text color. That makes an explicitly-set ForeColor equal to Control.DefaultForeColor look like "not set", so the adapter may override it with dark-mode/light-mode defaults. Consider treating the forecolor as explicit when ShouldSerializeForeColor() is true (e.g., ShouldSerializeForeColor() || ForeColor != DefaultForeColor).
PaintImage(e, layout);
Color preferredTextColor = Control.ForeColor != Forms.Control.DefaultForeColor
? Control.ForeColor
: Application.IsDarkModeEnabled
? Color.FromArgb(0xF0, 0xF0, 0xF0)
: SystemColors.WindowText;
src/System.Windows.Forms/System/Windows/Forms/Rendering/Button/AnimatedPopupButtonRenderer.cs:160
- UseAutomaticForeColor is now derived solely from ForeColor == Control.DefaultForeColor, which makes explicit ForeColor assignments to the default value indistinguishable from "not set". This can cause explicitly-set default ForeColor values to be ignored in favor of automatic/theme text. Consider aligning this with the same "not explicitly set AND still default" logic as the local useAutomaticForeColor calculation.
BackColor = faceColor,
ForeColor = foreColor,
SurfaceColor = button.Parent?.BackColor ?? button.BackColor,
UseAutomaticForeColor = button.ForeColor == Forms.Control.DefaultForeColor,
BorderColor = borderColor,
BorderWidth = flatAppearance.BorderSize,
src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/RadioButtonModernAdapter.cs:118
- Same as CheckBoxModernAdapter: using only (ForeColor != Control.DefaultForeColor) loses the ability to distinguish "explicitly set to default" from "not set". If a user sets ForeColor to the default to override inheritance, this will now fall back to the adapter's dark-mode/light-mode defaults instead. Consider using ShouldSerializeForeColor() || ForeColor != DefaultForeColor.
PaintImage(e, layout);
Color preferredTextColor = Control.ForeColor != Forms.Control.DefaultForeColor
? Control.ForeColor
: Application.IsDarkModeEnabled
? Color.FromArgb(0xF0, 0xF0, 0xF0)
: SystemColors.WindowText;
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fixes #14778
Root Cause
In the VisualStylesMode.Net11 modern rendering path, button-family controls (Button, CheckBox, RadioButton) relied too heavily on ShouldSerializeForeColor/BackColor to decide whether to use automatic colors.
This caused inherited colors from parent containers to be misclassified as either “not set” (fallback to automatic theme colors) or “custom colors,” which led to:
ForeColor inheritance being overridden unexpectedly (child controls not following GroupBox foreground updates)
BackColor inheritance being treated as explicit customization (child controls unexpectedly following GroupBox background updates)
Proposed changes
Customer Impact
Regression?
Risk
Screenshots
Before
Issue#1:

When a GroupBox ForeColor is changed at design time, child controls such as Button and CheckBox do not update their text color accordingly with VisualStylesMode.Net11 mode.
Behavior differs from VisualStylesMode.Classic.
Issue#2:

When a GroupBox BackColor is changed, a Button contained within the GroupBox unexpectedly reflects inherited BackColor updates with VisualStylesMode.Net11 mode.
Behavior differs from VisualStylesMode.Classic.
After
2026-08-25.110757.mp4
Test methodology
Test environment(s)
Microsoft Reviewers: Open in CodeFlow