Home > database >  WindowChrome button not hit-test visible when disabled
WindowChrome button not hit-test visible when disabled

Time:10-05

In WPF you can customize the caption bar using WindowChrome. Adding buttons in the non-client area is fairly simple as long as you remember to set WindowChrome.IsHitTestVisibleInChrome="True".

Now, there is a bug or unexpected/weird behavior when a disabled button is double-clicked. Nothing should happen, but instead the app is maximized.

Steps to reproduce

  1. Create a new WPF project. Preferably targeting .NET 6.
  2. Paste the code below in MainWindow.xaml.
  3. Run the app and double-click the button.

Expected: Nothing happens

Actual: The app is maximized

<Window x:Class="WpfChromeTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" WindowStyle="None" Height="450" Width="800">
    <WindowChrome.WindowChrome>
        <WindowChrome CaptionHeight="20" />
    </WindowChrome.WindowChrome>
    <Window.Template>
        <ControlTemplate TargetType="{x:Type Window}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="32" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Button Grid.Row="0" Width="200" Height="28" VerticalAlignment="Top"
                        Content="I'm disabled! DOUBLE-CLICK ME!"
                        WindowChrome.IsHitTestVisibleInChrome="True"
                        IsEnabled="False" />
            </Grid>
        </ControlTemplate>
    </Window.Template>
</Window>

What am I missing here? Is it a bug? And if so, is there a workaround?

CodePudding user response:

Double clicking on the title bar causes the window to change its state,

  1. when the button is enabled, the double click will be handled by the button and not passed to the title bar.
  2. when the button is disabled, the double click will be passed to the title bar, this will happen if you replace the button with any disabled UIElement.

So the current behavior is normal.

Is there a workaround?

Yes, If you want to disable WindowState change regardless of the button's IsEnabled value, wrap <Button/> with another UI element that will prevent the double click from being passed to the window's title bar if the button is disabled.

<ContentControl
    Grid.Row="0"
    Width="200"
    Height="28"
    VerticalAlignment="Top"
    WindowChrome.IsHitTestVisibleInChrome="True">
    <Button
        x:Name="MyButton"
        Content="I'm disabled! DOUBLE-CLICK ME!"
        IsEnabled="False" />
</ContentControl>

CodePudding user response:

When you double-click on the caption, the window is restored. This is by design and certainly not a bug.

If you want your Button to capture the click on the caption, you should not disable it.

You could still make it look like it's disabled if that's what you want.

Create a custom template and use the Tag property to determine whether your Button should like it's disabled:

<Button Grid.Row="0" Width="200" Height="28" VerticalAlignment="Top"
        Content="I'm disabled! DOUBLE-CLICK ME!"
        WindowChrome.IsHitTestVisibleInChrome="True"
        Tag="false">
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsDefaulted" Value="true">
                    <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
                    <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="true">
                    <Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
                    <Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
                    <Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
                    <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
                </Trigger>
                <Trigger Property="Tag" Value="false">
                    <Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
                    <Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
                    <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>
  • Related