11
votes

I have a control that is using a popup with some WPF controls inside of it, and StaysOpen="True". The problem is when clicking on the popup when the application doesn't have focus, the application does not receive focus. I've done a bit of research, and it seems like this may be due to the fact that popups are meant to be used for menus, so they don't have all of the proper windows message handlers hooked up. Here is a barebones sample to demoing the problem:

<Window x:Class="TestWindowPopupBehavior.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:TestWindowPopupBehavior="clr-namespace:TestWindowPopupBehavior" Title="MainWindow" Height="350" Width="525">
<Grid>
    <Popup StaysOpen="True" IsOpen="True" Placement="Center">
        <ListBox>
            <TextBlock>123</TextBlock>
            <TextBlock>123</TextBlock>
            <TextBlock>123</TextBlock>
            <TextBlock>123</TextBlock>
            <TextBlock>123</TextBlock>
            <TextBlock>123</TextBlock>
        </ListBox>
    </Popup>

</Grid>
</Window>
  1. Run the application.
  2. Interact with the listbox, which should work fine.
  3. Switch to another application.
  4. Click on the listbox while the application is not active. Nothing happens
  5. Click the application outside of the listbox.
  6. Click on the listbox. It is working now.

What I would expect to happen in step 4 would be the application would receive focus, and the listbox would select the new item.

Are there any workarounds to this problem, or something obvious I'm missing? I'm looking at rewriting the whole popup code with full-fledged windows, and re-implementing the behavior we have, but that seems really complicated just to fix a small problem like this.

2

2 Answers

6
votes

If you handle MouseLeftButtonDown event, you can call Window.Activate() method. but you should write it for each element - Popup and for all TextBlocks.

The problem you can met with is that on Windows you can swap mouse buttons, where left became right and vice versa (but I don't know how this works), so, may be you have to handle MouseRightButtonDown event.

0
votes

Today I came across this issue myself.

If you want, you can fix it globally by registering a class handler on the Popup class itself in the app.xaml.cs:

C#:

/// <inheritdoc />
protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(Popup), UIElement.PreviewMouseDownEvent, new RoutedEventHandler(Popup_PreviewMouseDownEvent));
}

/// <summary>
/// Ensures that the application is activated before the <see cref="UIElement.MouseDownEvent"/> is invoked on the Popup.
/// This solves an issue where the Popup seemed to be frozen if you focused out to another application and clicked back in the Popup itself.
/// </summary>
/// <param name="_"></param>
/// <param name="__"></param>
private void Popup_PreviewMouseDownEvent(object _, RoutedEventArgs __)
{
    Current?.MainWindow?.Activate();
}