Почему всплывающее окно WPF закрывается при щелчке по его фоновой области?

У меня есть элемент управления WPF Popup, который содержит некоторые элементы управления редактированием (списки, текстовые поля, флажки), расположенные с небольшим количеством пробелов.

Popup.StaysOpen установлен в False, что является обязательным. Если пользователь щелкает в другом месте приложения, операцию редактирования следует считать прерванной, и всплывающее окно закрывается.

К сожалению, всплывающее окно также закрывается всякий раз, когда пользователь щелкает в фоновой области всплывающего окна (пространство между элементами управления редактированием).

Я пробовал установить всплывающее окно Focusable. Я также попытался настроить дочерний элемент всплывающего окна (Border) на фокусировку. Ни на одном из фронтов не повезло.

Более того, кажется, что событие мыши проходит через всплывающее окно. Какой бы элемент ни находился под всплывающим окном, когда я щелкаю, он становится сфокусированным. И это несмотря на то, что для Popup и Border (на который я нажимаю) для IsHitTestVisible и Focusable установлено значение true.


person Drew Noakes    schedule 06.03.2009    source источник


Ответы (5)


В конце концов, я обнаружил, что сработало следующее. Данный...

<Popup x:Name="_popup"
       StaysOpen="False"
       PopupAnimation="Slide"
       AllowsTransparency="True">

... Я использовал этот код в конструкторе после вызова _2 _...

// Ensure that any mouse event that gets through to the
// popup is considered handled, otherwise the popup would close
_popup.MouseDown += (s, e) => e.Handled = true;
person Drew Noakes    schedule 06.03.2009
comment
Отличное решение! Я даже смог сделать это с элементом управления, определенным в Generic.xaml, с помощью EventToCommand, передав EventArgs команде и затем установив Handled = True. Спасибо! - person Dror; 16.05.2012
comment
Еще один способ скрыть обработчик ошибок в сложной ситуации - создать класс ArmouredPopup, производный от Popup. Он может отменять OnMouseDown. Я считаю это ошибкой в ​​классе всплывающих окон по умолчанию. - person Adrian Ratnapala; 04.04.2014
comment
Я бы сказал, что это не лучшее решение не потому, что то, что вы предоставили, плохо (на самом деле это хорошо), а потому, что разработчикам не следует этого делать. Я играл с этим целую вечность, и похоже, что событие щелчка распространяется на другой обработчик событий, который, в свою очередь, снова закрывает всплывающее окно. Вероятно, проблема с MS Connect уже открыта, поэтому будем надеяться, что команда MS выпустит исправление. (@AdrianRatnapala согласился) - person Kezzer; 08.07.2014

Кажется странным, что он игнорирует Focusable on the Popup и Border. Мне удалось решить вашу проблему, изменив StaysOpen в триггере, когда мышь находится над границей:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ToggleButton x:Name="btnPop" Content="Pop!" Width="100" Height="50"/>
    <Popup Placement="Bottom" PlacementTarget="{Binding ElementName=btnPop}" IsOpen="{Binding IsChecked, ElementName=btnPop}">
        <Popup.Style>
            <Style TargetType="{x:Type Popup}">
                <Setter Property="StaysOpen" Value="False"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsMouseOver, ElementName=brd}" Value="True">
                        <Setter Property="StaysOpen" Value="True"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Popup.Style>
        <Border x:Name="brd" Background="White" BorderThickness="1" BorderBrush="Black">
            <StackPanel>
                <TextBox Margin="10"/>
                <TextBlock Text="Some text is here." Margin="10"/>
                <TextBox Margin="10"/>
            </StackPanel>            
        </Border>
    </Popup>
</Grid>
person Robert Macnee    schedule 06.03.2009
comment
Собственно, у меня это работает. Важно отметить одну вещь, @RobertMacnee, - это то, что вы должны убедиться, что вы не установили свойство StaysOpen в самом элементе Popup, оно должно быть оставлено на усмотрение установщика стиля и запускаться полностью, иначе это не сработает. - person Kezzer; 08.07.2014

Я думаю, у вас есть проблемы с прозрачностью. Попробуйте установить фоновую кисть во всплывающем окне.

person Bryan Anderson    schedule 06.03.2009
comment
Спасибо за Ваш ответ. Элемент управления границей заполняет всю область всплывающего окна и имеет твердый набор кистей. - person Drew Noakes; 06.03.2009

Разве ваше всплывающее окно не вложено в ToggleButton или другую кнопку? Тогда было бы логично остановить перенаправленное событие на уровне всплывающего окна.

person PaN1C_Showt1Me    schedule 13.07.2009

вы можете установить StayOpen = true и установить таймер во всплывающем окне события MouseLeave timer.Start (), например, через 3 секунды закрыть это всплывающее окно в событии MouseEnter, timer.Stop () . Это будет работать.

person dubuyunjie    schedule 17.07.2013