Light theme `Foreground` does not have correct value unless `RequestedTheme` is set
Describe the bug
WinUI sets the DefaultTextForegroundThemeBrush for light theme to #E4000000 instead of fully opaque black. However, this is not applied consistently unless element-level RequestedTheme is set explicitly to Light (e.g. TextBlock.Foreground, ContentPresenter.Foreground and BitmapIcon.Foreground are all still fully opaque black).
Steps to reproduce the bug
- Create a blank WinUI Packaged app or a blank UWP app with WinUI 2.8
- In
MainPage.xamlorMainWindow.xamladd the following content:
<Grid ColumnDefinitions="*,*" Loaded="Grid_Loaded">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="TextBlock1" Text="Test" FontWeight="Black" FontSize="60" />
<BitmapIcon x:Name="BitmapIcon1" UriSource="ms-appx:///Assets/StoreLogo.png" />
</StackPanel>
<StackPanel RequestedTheme="Light" Grid.Column="1" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="TextBlock2" Text="Test" FontWeight="Black" FontSize="60" />
<BitmapIcon x:Name="BitmapIcon2" UriSource="ms-appx:///Assets/StoreLogo.png" />
</StackPanel>
</Grid>
- In the code-behind put the following:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine(((SolidColorBrush)TextBlock1.Foreground).Color);
Debug.WriteLine(((SolidColorBrush)BitmapIcon1.Foreground).Color);
Debug.WriteLine(((SolidColorBrush)TextBlock2.Foreground).Color);
Debug.WriteLine(((SolidColorBrush)BitmapIcon2.Foreground).Color);
}
- Ensure your OS is running in light theme (or go to
App.xamland set theRequestedThemethere toLight). - Run the application.
- Notice that the text and the icon on the left have fully opaque black color whereas the same is slightly lighter on the right side:

- See the debug Output window, notice the colors also match what you see on the screen:

Expected behavior
The #E4000000 color should be applied consistently (or fully opaque black should be used).
Screenshots

NuGet package version
WinUI 3 - Windows App SDK 1.3.0: 1.3.230331000 WinUI 3 - Windows App SDK 1.2.5: 1.2.230313.1 UWP + WinUI 2.8
Windows version
Windows 11 (22H2): Build 22621
Additional context
Happens even in WinUI 2.8 + UWP
This may be due to how DP default values work in WinUI.
Whenever a default value needs to be read, DependencyProperty::GetDefaultValue is called. For Foreground DPs specifically, that's calculated from CoreServices and is cached there (CCoreServices::GetDefaultTextBrush).
Then, whenever you set RequestedTheme, it will cause CFrameworkElement::NotifyThemeChangedForInheritedProperties to be called which will re-lookup DefaultTextForegroundThemeBrush. It may be that they are called at different timings of the app lifecycle where it yields different results? I'm not sure, such a hypothesis looking at the relevant pieces of code here.