Skip to content

Disabled Appearance="Primary" button renders white text on light background (invisible) since 4.2.1 #1699

Closed

Description

@ValeriiN

Describe the bug

In WPF-UI 4.2.1, a ui:Button with Appearance="Primary" and IsEnabled="False" keeps the white "on accent" foreground from the enabled-Primary state, leaving the disabled label invisible on the light disabled background. The same XAML in 4.2.0 correctly renders the disabled label in grey.

The regression appears to come from PR #1680 ("Proper foreground on Button content"), which moved the Disabled foreground setter from per-element (TargetName="ContentPresenter" / TargetName="ControlIcon" with TextElement.Foreground) to a single Style-level <Setter Property="Foreground" .../>. Because the Appearance="Primary" trigger is declared after the IsEnabled="False" trigger in Button.xaml and also sets Foreground (to AccentButtonForeground), it wins for disabled Primary buttons.

To Reproduce

Repro

Minimal, isolated reproduction — only <PackageReference Include="WPF-UI" />, the stock ThemesDictionary + ControlsDictionary, ApplicationThemeManager.Apply(ApplicationTheme.Light), and a bare ui:FluentWindow. No additional resources or styles.

App.xaml

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
             StartupUri="MainWindow.xaml">
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ui:ThemesDictionary Theme="Light" />
        <ui:ControlsDictionary />
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

App.xaml.cs

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    ApplicationThemeManager.Apply(ApplicationTheme.Light);
}

MainWindow.xaml

<ui:FluentWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
                 x:Class="WpfUiButtonRepro.MainWindow"
                 Width="720" Height="280">
  <StackPanel Margin="24">
    <TextBlock Text="Enabled" />
    <WrapPanel>
      <ui:Button Appearance="Primary"   Content="Primary"   Margin="4" />
      <ui:Button Appearance="Secondary" Content="Secondary" Margin="4" />
      <ui:Button Appearance="Success"   Content="Success"   Margin="4" />
      <ui:Button Appearance="Caution"   Content="Caution"   Margin="4" />
      <ui:Button Appearance="Danger"    Content="Danger"    Margin="4" />
    </WrapPanel>

    <TextBlock Text="Disabled" />
    <WrapPanel>
      <ui:Button Appearance="Primary"   Content="Primary"   IsEnabled="False" Margin="4" />
      <ui:Button Appearance="Secondary" Content="Secondary" IsEnabled="False" Margin="4" />
      <ui:Button Appearance="Success"   Content="Success"   IsEnabled="False" Margin="4" />
      <ui:Button Appearance="Caution"   Content="Caution"   IsEnabled="False" Margin="4" />
      <ui:Button Appearance="Danger"    Content="Danger"    IsEnabled="False" Margin="4" />
    </WrapPanel>
  </StackPanel>
</ui:FluentWindow>

Actual

In 4.2.1 the disabled Primary button keeps Foreground = AccentButtonForeground (white), so the label is invisible against the light disabled background.

4.2.0 (correct) 4.2.1 (regression)

Suspected cause

In src/Wpf.Ui/Controls/Button/Button.xaml:

  • 4.2.0 disabled trigger applied the foreground per-element:
    <Setter TargetName="ControlIcon"      Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
    <Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
  • 4.2.1 disabled trigger sets it at the Style level:
    <Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />

The later Trigger Property="Appearance" Value="Primary" also sets Foreground="{DynamicResource AccentButtonForeground}", and Style-level triggers are evaluated in declaration order (later wins), so the disabled foreground no longer takes effect for Primary buttons.

Workaround

A BasedOn style with a MultiTrigger placed in window-scoped resources (does not work at App level for the usual implicit-style + BasedOn={x:Type ui:Button} lookup-order reasons):

<ui:FluentWindow.Resources>
  <Style TargetType="ui:Button" BasedOn="{StaticResource {x:Type ui:Button}}">
    <Style.Triggers>
      <MultiTrigger>
        <MultiTrigger.Conditions>
          <Condition Property="IsEnabled" Value="False" />
          <Condition Property="Appearance" Value="Primary" />
        </MultiTrigger.Conditions>
        <Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
      </MultiTrigger>
    </Style.Triggers>
  </Style>
</ui:FluentWindow.Resources>

Suggested fix

Either restore the per-element TargetName=... setters in the Disabled trigger, or move the Appearance="Primary" trigger above the IsEnabled="False" trigger so the disabled Style setter wins.

Environment

  • WPF-UI 4.2.1 (regression) vs 4.2.0 (correct)
  • .NET 8 (net8.0-windows)
  • Windows 11 Pro
  • Theme: ApplicationTheme.Light (also reproduces with Dark)
  • ui:FluentWindow host, ApplicationThemeManager.Apply(...) at startup, no other resources merged

Expected behavior

Expected

The disabled Appearance="Primary" button should render the "Primary" label in the disabled-foreground colour (grey), as it does in 4.2.0 and as the other appearances (Secondary/Success/Caution/Danger) still do in 4.2.1.

Screenshots

Image

OS version

Windows 11 Pro

.NET version

.NET 8 (net8.0-windows)

WPF-UI NuGet version

WPF-UI 4.2.1

Additional context

No response

Activity

  1. pomianowski commented on Apr 30, 2026

    @pomianowski
    Member

    Possibly related #1680, @dkuaf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions