Skip to content

Commit d466cb9

Browse files
Fix low-contrast TreeViewItem chevron in WPF Gallery nav pane
The Fluent nav TreeView expand/collapse chevron renders as a thin FontSize-10 glyph whose anti-aliased strokes only reach ~2.6:1 against the nav background, below the WCAG/MAS 1.4.11 3:1 non-text contrast minimum. The glyph size is baked into the sealed theme template via a StaticResource and cannot be overridden through application resources, so the chevron FontSize is enlarged on each realized nav container in code-behind, rendering the full stroke at ~3.9:1 in every theme. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0238f8a commit d466cb9

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

Sample Applications/WPFGallery/MainWindow.xaml.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ private void ControlsList_PreviewMouseLeftButtonUp(object sender, MouseButtonEve
206206

207207
private void ControlsList_Loaded(object sender, RoutedEventArgs e)
208208
{
209+
ResizeNavChevrons();
209210
if (ControlsList.Items.Count > 0)
210211
{
211212
TreeViewItem firstItem = (TreeViewItem)ControlsList.ItemContainerGenerator.ContainerFromItem(ControlsList.Items[0]);
@@ -216,6 +217,52 @@ private void ControlsList_Loaded(object sender, RoutedEventArgs e)
216217
}
217218
}
218219

220+
// The Fluent nav chevron is a thin FontSize-10 glyph that anti-aliases to ~2.6:1 (below the
221+
// WCAG/MAS 1.4.11 3:1 minimum); enlarging it renders the full stroke at ~3.9:1 in any theme.
222+
private const double NavChevronFontSize = 12d;
223+
224+
// Only the top-level nav items expand, and their containers are realized by the time the
225+
// TreeView is loaded, so resizing their chevrons once here is sufficient. The size is baked into
226+
// the sealed theme template via a StaticResource, so it must be set on the realized glyph.
227+
private void ResizeNavChevrons()
228+
{
229+
foreach (object item in ControlsList.Items)
230+
{
231+
if (ControlsList.ItemContainerGenerator.ContainerFromItem(item) is TreeViewItem tvi
232+
&& FindChevronIcon(tvi) is TextBlock chevron)
233+
{
234+
chevron.FontSize = NavChevronFontSize;
235+
}
236+
}
237+
}
238+
239+
private static TextBlock? FindChevronIcon(DependencyObject root)
240+
{
241+
int count = VisualTreeHelper.GetChildrenCount(root);
242+
for (int i = 0; i < count; i++)
243+
{
244+
DependencyObject child = VisualTreeHelper.GetChild(root, i);
245+
246+
// Each item owns a single chevron in its own header; don't descend into nested items.
247+
if (child is TreeViewItem)
248+
{
249+
continue;
250+
}
251+
252+
if (child is TextBlock { Name: "ChevronIcon" } chevron)
253+
{
254+
return chevron;
255+
}
256+
257+
if (FindChevronIcon(child) is TextBlock found)
258+
{
259+
return found;
260+
}
261+
}
262+
263+
return null;
264+
}
265+
219266
private void SelectedItemChanged(TreeViewItem? tvi)
220267
{
221268
ControlsList_SelectedItemChanged();

0 commit comments

Comments
 (0)