I've noticed an odd behavior with WPF where a button that has the Focusable property set to false will fail to refresh its visual state if the button is occluded by a popup (ex: a file dialog).
On to the good stuff, here is a minimal code example:
XAML
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="200" Width="200"
WindowStartupLocation="CenterScreen">
<Button Name="button" Focusable="False" Content="Button" Click="Button_Click" Height="100" Width="100">
<!-- Style is optional, but makes issue easier to see -->
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Gray" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Gainsboro" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Code-behind
using System.Windows;
using Microsoft.Win32;
namespace WpfApplication1
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
new OpenFileDialog().ShowDialog();
}
}
}
When you run the application, click the button and move the open dialog that opens up so that it covers over the button. When the dialog opens on top of the button, and if the mouse is not over the button when you close the dialog (ex: press ESC to close the dialog) then the button will still appear to be pressed until you run your mouse over the button forcing a refresh.
Bits of detail I've accrued:
- Focusable appears to be the heart of the issue. If it is not set to False, the button behaves as expected
- The problem still occurs without any style defined. I included the Style because it makes the problem easier to see.
- If the button is partially occluded, then the button will partially refresh. This hints towards how the region is being invalidated for painting.
- Observed using WPF 4
Unsuccessful approaches I have tried:
- Using a Command instead of a Click handler
- Using Dispatcher.BeginInvoke to call ShowDialog
- Calling UpdateLayout on the Window and/or Button
- Calling InvalidateVisual on the Window and/or Button
I will greatly appreciate any help or suggestions that are offered. :)