Взаимодействие всплывающего окна и кнопки переключения в wpf

#wpf #binding #popup #togglebutton

#wpf #привязка #всплывающее окно #кнопка переключения

Вопрос:

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

Я настроил это, установив для свойства StaysOpen всплывающего окна значение false и установив для свойства IsChecked кнопки переключения двустороннюю привязку к свойству isOpen всплывающего окна.

Все хорошо, за исключением одного случая — при отмеченной кнопке и открытом всплывающем окне нажатие кнопки не приводит к закрытию всплывающего окна или возврату кнопки в положение unchecked.

Я полагаю, это должно быть связано с тем, что нажатие кнопки приводит к тому, что логика StaysOpen всплывающего окна устанавливает для свойства isOpen всплывающего окна значение false. В свою очередь, это снимает флажок с кнопки переключения. Это должно произойти до того, как будет обработан мой щелчок по кнопке — таким образом, щелчок повторно проверяет кнопку, то есть состояние гонки.

Есть идеи, как я могу добиться желаемого поведения?

Ответ №1:

Если ваше предположение верно, вам понадобится пользовательский класс Popup, подобный следующему:

 public class MyPopup : Popup {
    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) {
        bool isOpen = this.IsOpen;
        base.OnPreviewMouseLeftButtonDown(e);

        if (isOpen amp;amp; !this.IsOpen)
            e.Handled = true;
    }
}
  

Возможно, вам потребуется удалить !this.IsOpen из инструкции if. Если вместо этого вы используете MyPopup, это предотвратит попадание события MouseLeftButtonDown в кнопку переключения.

Комментарии:

1. Проблема с этим подходом заключается в том, что если вы щелкаете вне всплывающего окна, это фактически ни на что не нажимает. Вы не хотите нажимать на ToggleButton , но вы хотите нажимать на все остальное

Ответ №2:

Оба вышеуказанных решения имеют проблемы. Вот еще одно решение, которое использует обработчики событий вместо привязки, но позволяет избежать проблемы с потерянным щелчком мыши, на которую указал svick в решении MyPopup, и проблем с ClickMode = Press. Xaml выглядит следующим образом:

 <ToggleButton Name="OptionsButton" Checked="OptionsButton_OnChecked" Unchecked="OptionsButton_OnUnchecked" />
<Popup Name="OptionsPopup" StaysOpen="False" Closed="OptionsPopup_OnClosed"/>
  

И код :

     void OptionsPopup_OnClosed(object sender, EventArgs e)
    {
        if (OptionsButton != Mouse.DirectlyOver)
            OptionsButton.IsChecked = false;
    }

    void OptionsButton_OnChecked(object sender, RoutedEventArgs e)
    {
        OptionsPopup.IsOpen = true;
    }

    void OptionsButton_OnUnchecked(object sender, RoutedEventArgs e)
    {
        OptionsPopup.IsOpen = false;
    }
  

Комментарии:

1. Вы можете избавиться от обработчиков OnChecked и OnUnchecked, связав OptionsPopup. Я открыт для OptionsButton. Проверено, a.la . <Popup x:Name="OptionsPopup" IsOpen="{Binding ElementName=OptionsButton, Path=IsChecked, Mode=OneWay}" /> . Убедитесь, что вы установили Mode=OneWay .

Ответ №3:

Решение-установить привязки TwoWay между isopen значение свойства из контекстного меню и на этот флажок установлен собственность выключатель — затем установите ClickMode собственность выключатель на пресс. Вуаля!

Комментарии:

1. также не работает .. щелчок вне всплывающего окна не закрывает всплывающее окно