Sunday, November 21, 2010

WPF - Modal Dialog missing Keyboard messages

I have noticed a weird behavior with Modal windows in WPF. As we know a modal window is supposed to implement its own message loop. Once this is displayed, all user navigation mouse and keyboard messages targeted to any other window is ignored by main message loop of the application. WPF seems to have issues with keyboard messages and it still seems not to block the keyboard messages under certain scenario. Let me explain this through an example. Let us create a window. We call this WindowModalOwner. This would suppose to be the window opening a modal window. The XAML of the window is as follows:
<Window x:Class="MultiBinding_DifferentVMs.WindowModalOwner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowModelOwner" Height="300" Width="463">
<Grid>
<TextBlock Height="30" Margin="70,10,82,0" Name="textBlock1" VerticalAlignment="Top" Text="Modal Owner Window"
FontFamily="Arial" FontSize="20" HorizontalAlignment="Center" />
<Button Height="54" Margin="71,0,91,53"
Name="btnModal" VerticalAlignment="Bottom" Click="button1_Click">Button</Button>
<TextBox Height="29" Margin="71,49,85,0" Name="textBox1" VerticalAlignment="Top" />
<TextBox Height="31" Margin="71,93,83,0" Name="textBox2" VerticalAlignment="Top" />
</Grid>
</Window>

At the button click, we want to display a Modal Dialog. The code behind is as follows:
public partial class WindowModalOwner : Window
{
public WindowModalOwner()
{
InitializeComponent();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
var wnd = new WindowModalChild();
wnd.ShowDialog();
}
}

The child window is as follows:
<Window x:Class="MultiBinding_DifferentVMs.WindowModalChild"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowModalChild" Height="300" Width="481">
<Grid>
<TextBlock FontFamily="Arial" FontSize="20" Height="30"
Margin="159,63,105,0" Name="textBlock1" Text="Modal Dialog" VerticalAlignment="Top" />
<Button Margin="111,123,69,85" Name="btnTest">Button</Button>
</Grid>
</Window>

Now run the application, it shows the application as follows:



Click the button and chil window would display as follows. Try clicking back the WindowModalOwner window. Since this is a modal dialog, you would not be able to do anything and would just get a beep.


Now experience the weird thing now. Since we have not explicitly set ShowInTaskBar property, the default value is set, which is True. Both window are shown in the taskbar as follows:



Now the weird thing happens. Select WindowModalOwner from taskbar and this would show the window pushing its modal child on the back. You would not be able to click on it and still you just hear the beep. This is expected. Now start navigating through Keyboard using Tab, Ctrl + Tab and space bar. All navigation still works on the owner window. If you set the focus on a button and hit space bar then click also works. What!!!

This is certainly an issue. Now is there a fix for this? There is certainly. Just update the code which shows the child window as follows:
private void button1_Click(object sender, RoutedEventArgs e)
{
var wnd = new WindowModalChild();
wnd.Owner = this;
wnd.ShowDialog();
}

We just have to set the owner of the child window as the current window and everything works now. If you are launching this dialog as a modal window from a Windows form then you can use WindowInteropHelper to set the Winform's parent windows's handle as the owner of this modal window. This is kind of similar issue which is presented here. But he was noticing a slightly different issue but the cause is same.

http://blogs.msdn.com/b/mhendersblog/archive/2005/10/04/476921.aspx

No comments: