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.
WPF
project. Preferably targeting .NET 6
.MainWindow.xaml
.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?
The accepted answer got it right. The reason why it works can be seen in WindowChromeWorker.cs(670) where the call to UIElement.InputHitTest will indeed skip any disabled element. However, on line 673 we find the magic that allows for the suggested solution:
When the parent element has WindowChrome.IsHitTestVisibleInChrome
set to true
, the callback will correctly return HTCLIENT
, effectively swallowing our double click.
In the provided sample, we could simply replace <Grid>
with the following, to get the desired behavior:
<Grid WindowChrome.IsHitTestVisibleInChrome="True">
Double clicking on the title bar causes the window to change its state,
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>