-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Enable DataGridView dark mode theming via AppContext switch #14267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cbb3bcc
0466578
0e46f9d
20ce8c5
cc7aa78
f9dd611
2af28f4
dcf698f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,48 @@ namespace System.Windows.Forms; | |
|
|
||
| public partial class DataGridView | ||
| { | ||
| /// <summary> | ||
| /// Applies dark mode theming to the DataGridView when the application is running | ||
| /// in dark mode. This is called automatically from <see cref="OnHandleCreated"/> | ||
| /// when the <c>System.Windows.Forms.DataGridViewDarkModeTheming</c> AppContext switch | ||
| /// is enabled (default for .NET 10+). | ||
| /// </summary> | ||
| private void ApplyDarkModeTheming() | ||
| { | ||
| Color surface = SystemColors.Window; | ||
| Color onSurface = SystemColors.WindowText; | ||
| Color headerBg = SystemColors.ControlDarkDark; | ||
| Color headerFg = SystemColors.ActiveCaptionText; | ||
| Color selectionBg = Color.FromArgb(0x33, 0x66, 0xCC); | ||
|
||
| Color selectionFg = Color.White; | ||
|
|
||
| // Disable the header's system theme so that our custom styles are not overridden by the system. | ||
| EnableHeadersVisualStyles = false; | ||
|
|
||
| // Table body | ||
| BackgroundColor = surface; | ||
| DefaultCellStyle.BackColor = surface; | ||
| DefaultCellStyle.ForeColor = onSurface; | ||
|
|
||
| // Column headers | ||
| ColumnHeadersDefaultCellStyle.BackColor = headerBg; | ||
| ColumnHeadersDefaultCellStyle.ForeColor = headerFg; | ||
|
|
||
| // Light-colored dividing line | ||
| GridColor = ControlPaint.Light(surface, 0.50f); | ||
|
|
||
| // Row headers | ||
| RowHeadersDefaultCellStyle.BackColor = headerBg; | ||
| RowHeadersDefaultCellStyle.ForeColor = headerFg; | ||
|
|
||
| // Selected state - use Color.Empty so header selection follows body selection | ||
| RowHeadersDefaultCellStyle.SelectionBackColor = Color.Empty; | ||
| ColumnHeadersDefaultCellStyle.SelectionBackColor = Color.Empty; | ||
|
|
||
| DefaultCellStyle.SelectionBackColor = selectionBg; | ||
| DefaultCellStyle.SelectionForeColor = selectionFg; | ||
| } | ||
|
|
||
| protected virtual void AccessibilityNotifyCurrentCellChanged(Point cellAddress) | ||
| { | ||
| if (cellAddress.X < 0 || cellAddress.X >= Columns.Count) | ||
|
|
@@ -2853,6 +2895,20 @@ private void BuildInheritedColumnHeaderCellStyle(DataGridViewCellStyle inherited | |
| inheritedCellStyle.SelectionForeColor = dataGridViewStyle.SelectionForeColor; | ||
| } | ||
|
|
||
| // Inherit SortGlyphColor for column header sort arrow | ||
| if (cellStyle is not null && !cellStyle.SortGlyphColor.IsEmpty) | ||
| { | ||
| inheritedCellStyle.SortGlyphColor = cellStyle.SortGlyphColor; | ||
| } | ||
| else if (!columnHeadersStyle.SortGlyphColor.IsEmpty) | ||
| { | ||
| inheritedCellStyle.SortGlyphColor = columnHeadersStyle.SortGlyphColor; | ||
| } | ||
| else if (!dataGridViewStyle.SortGlyphColor.IsEmpty) | ||
| { | ||
| inheritedCellStyle.SortGlyphColor = dataGridViewStyle.SortGlyphColor; | ||
| } | ||
|
|
||
| inheritedCellStyle.Font = cellStyle?.Font ?? columnHeadersStyle.Font ?? dataGridViewStyle.Font; | ||
|
|
||
| if (cellStyle is not null && !cellStyle.IsNullValueDefault) | ||
|
|
@@ -15242,6 +15298,12 @@ protected override void OnHandleCreated(EventArgs e) | |
| OnGlobalAutoSize(); | ||
| } | ||
|
|
||
| // Automatically apply dark mode theming when enabled via quirk switch. | ||
| if (Application.IsDarkModeEnabled && AppContextSwitches.DataGridViewDarkModeTheming) | ||
| { | ||
| ApplyDarkModeTheming(); | ||
| } | ||
|
|
||
| SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1435,6 +1435,18 @@ private static Bitmap GetBitmap(string bitmapName) => | |
| ? ControlPaint.LightLight(baseline) | ||
| : SystemColors.ControlLightLight; | ||
| } | ||
| else if (Application.IsDarkModeEnabled) | ||
| { | ||
| // In Dark Mode, use higher contrast colors for better visibility. | ||
| // For dark backgrounds, we need lighter colors that stand out. | ||
| darkColor = darkDistance < ContrastThreshold | ||
| ? ControlPaint.Light(baseline, 0.5f) | ||
| : SystemColors.ControlLight; | ||
|
|
||
| lightColor = lightDistance < ContrastThreshold | ||
| ? ControlPaint.LightLight(baseline) | ||
| : SystemColors.ControlLightLight; | ||
| } | ||
|
Comment on lines
+1438
to
+1449
|
||
| else | ||
| { | ||
| darkColor = darkDistance < ContrastThreshold | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 'if' statements can be combined.