我有一个包含Togglebutton和Popup的控件。单击ToggleButton时,将显示弹出窗口。取消选中ToggleButton时,弹出窗口应该关闭。此外,单击远离弹出窗口会导致它关闭,并导致Togglebutton取消选中。
我通过将Popup的StaysOpen属性设置为false并将切换按钮的IsChecked属性设置为与Popup的IsOpen属性双向绑定来设置它。
一切都很好,除了一个案例 - 选中按钮并弹出窗口,单击按钮不会导致弹出窗口关闭,或者按钮返回未选中状态。
我相信这一定是因为单击该按钮会导致Popup的StaysOpen逻辑将Popup的IsOpen属性设置为false。反过来,这会将Togglebutton设置为未选中状态。这必须在我点击按钮处理之前发生 - 所以点击会重新检查按钮,即竞争条件。
知道我怎么能得到我想要的行为吗?
答案 0 :(得分:10)
如果您的假设是正确的,您需要一个自定义的Popup类,如下所示:
public class MyPopup : Popup {
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) {
bool isOpen = this.IsOpen;
base.OnPreviewMouseLeftButtonDown(e);
if (isOpen && !this.IsOpen)
e.Handled = true;
}
}
您可能需要从if语句中删除!this.IsOpen
。如果您使用MyPopup,它将阻止MouseLeftButtonDown事件到达ToggleButton。
答案 1 :(得分:7)
上述两种解决方案都存在问题。这是使用事件处理程序而不是绑定的另一种解决方案,但确实避免了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;
}
答案 2 :(得分:1)
解决方案是在Popup的 IsOpen 属性和ToggleButton的 IsChecked 属性之间设置TwoWay绑定 - 然后设置 ClickMode ToggleButton的属性为按。瞧!