#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. также не работает .. щелчок вне всплывающего окна не закрывает всплывающее окно