WPF中弹出框和切换按钮的交互

11
我有一个控件,其中包含一个Togglebutton和一个Popup。当单击Togglebutton时,会弹出Popup。当取消选中ToggleButton时,Popup应关闭。此外,单击Popup之外的区域也应导致其关闭,并导致ToggleButton取消选中。
我通过将Popup的StaysOpen属性设置为false,并将ToggleButton的IsChecked属性双向绑定到Popup的IsOpen属性来设置它们。
一切都很好,除了一个情况-当按钮被选中且Popup打开时,单击按钮不会导致Popup关闭,也不会使按钮变为取消选中状态。
我认为这是因为单击按钮会导致Popup的StaysOpen逻辑将Popup的IsOpen属性设置为false。反过来,这会将ToggleButton设置为未选中。这必须在我的按钮单击被处理之前发生-因此单击重新选中按钮,即竞争条件。
您有什么想法可以实现我想要的行为吗?
3个回答

10

如果你的假设是正确的,你需要一个自定义的弹出窗口类,如下所示:

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,它会阻止鼠标左键按下事件到达ToggleButton。


1
这种方法的问题在于,如果你点击弹出窗口之外的地方,它实际上并没有点击任何东西。你并不想点击ToggleButton,而是想点击其他所有东西。 - svick

8

以上两个解决方案都存在问题。以下是另一种使用事件处理程序而不是绑定的解决方案,但避免了MyPopup解决方案中svick指出的丢失点击问题和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;
    }

4
你可以通过绑定OptionsPopup.IsOpen到OptionsButton.IsChecked来摆脱OnChecked和OnUnchecked处理程序,例如 <Popup x:Name="OptionsPopup" IsOpen="{Binding ElementName=OptionsButton, Path=IsChecked, Mode=OneWay}" />。确保设置 **Mode=OneWay**。 - kcnygaard

1
解决方案是在弹出窗口的 IsOpen 属性和切换按钮的 IsChecked 属性之间设置双向绑定,然后将切换按钮的 ClickMode 属性设置为 Press。完成!

3
也不起作用... 点击弹出窗口外部无法关闭弹出窗口。 - mike01010

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接